`
谁解怨妇心
  • 浏览: 28214 次
  • 性别: Icon_minigender_2
  • 来自: 广州
社区版块
存档分类
最新评论

死循环不死

阅读更多
今天在看雪看到一个帖:
引用

#include <iostream>
using namespace std;
int main()
{
cout<<"hello world!"<<endl;
__asm jmp main
return 0;
}

这个函数为啥不是死循环?怎么执行一会就结束?

按理说这应该是一个死循环,但编译后运行了一下却一会儿就退出了
小小改动一下,加入一个计数用的变量,再运行一下
#include <iostream>
using namespace std;
int a=0;

int main()
{
	a++;
	cout<<a<<endl;
	__asm jmp main
return 0;
}

在debug编译方式下运行到退出的时候,a的值是12918,而在release编译方式的情况下,则是19889.
这问题太诡异了!
但真的诡异吗?
转到汇编语言下看看下(本来用VC++6就可以看了,但用着怎么都不顺手,于是就换成od)
main函数的开头如下:
debug方式:
引用

00401560 > > \55            push    ebp
00401561   .  8BEC          mov     ebp, esp
00401563   .  83EC 40       sub     esp, 40
00401566   .  53            push    ebx
00401567   .  56            push    esi
00401568   .  57            push    edi

release方式:
引用

00401000   $  55            push    ebp
00401001   .  8BEC          mov     ebp, esp
00401003   .  83EC 24       sub     esp, 24
00401006   .  53            push    ebx
00401007   .  56            push    esi
00401008   .  57            push    edi

这两段代码可以说是熟悉得不能再熟悉的了函数开头的保存寄存器以及开辟临时变量的代码。而在函数结束的时候保存在栈中的值会弹出来。
于是上面那个死循环的问题就出现了:每个循环都往栈中压几次,但却又得不到释放,而栈空间不是无限大的,于是乎,程序就只好退出了。而用od运行后得到的终止代码是C0000005,这正是访问了无效的内存的错误代码。
为了再验证一下,再做一个小学的数学题:
在debug方式下,每次循环将80个字节压到栈中,而在循环12918次后,总共填了1033440个字节到栈中;
在release方式下,每次循环将52个字节压到栈中,而在循环19889次后,总共填了1034228个字节到栈中。
而这两个数值正好接近了1mb,这正是VC++6中默认的栈大小!

然后,再改动一下代码
#include <iostream>
using namespace std;
int a=0;

int main()
{
	for(;;)
	{
		a++;
		cout<<a<<endl;
		__asm push eax
	}
	return 0;
}

同样是运行了一会儿就退出了,而由于每次循环都只是往栈中压进了4个字节,所以两种编译方式得到的结果差别不大,均为250000左右。
分享到:
评论

相关推荐

    qt 多线程 防止主线程做循环操作导致界面假死

    在使用Qt进行应用程序开发时,有时我们可能会遇到主线程因为执行耗时的循环操作而使得用户界面(UI)无响应,这种现象通常被称为“界面假死”或“UI冻结”。为了解决这个问题,我们可以利用Qt提供的多线程机制,将耗时...

    贪吃蛇:常规版+不死版+双子版(看看你的CPU是并行还是并发)

    游戏的核心算法涉及到了循环、条件判断和数组操作,这些都是计算机编程的基础。蛇的移动通常是由一个定时器控制的,每次触发更新蛇的位置。这种设计方式体现了计算机的顺序执行能力,即程序按照预定的步骤逐条执行。...

    一个都不能死HTML5网页小游戏代码

    - 动画框架:可能使用请求动画帧(requestAnimationFrame)来实现流畅的游戏循环。 - 模块化和组织结构:为了代码可维护性,开发者可能使用模块化技术,如CommonJS或ES6的import/export语法。 HTML5游戏开发通常...

    亲子阅读死了万次的猫学习教案.pptx

    故事讲述了一只不死的虎斑猫历经多次生命轮回,分别作为国王的猫、水手的猫、马戏团魔术师的猫、小偷的猫、孤独老婆婆的猫和小女孩的猫,每次都因各种原因死去,而猫自己从未为死亡哭泣。直到最后,猫变成了一只...

    亲子阅读死了万次的猫PPT课件.pptx

    然而,生命的循环不可避免,白猫最终离开了猫,这让猫首次感受到了失去爱人的痛苦,它哭了,哭了整整100万次。猫的哭泣不仅是对白猫的思念,也是对自己过去冷漠生活的悔悟,它明白了生命的价值在于连接与爱。 故事...

    绿色循环圈各成长塔攻略要点PPT学习教案.pptx

    4. 11 波以后出了光环怪基本打不死,这时候多利用 X 和雷霆打(减攻击在能打死的情况下尽量留 X),这期间随着蓝的增长升级锤子,多余的钱留着升级天神(这里攒到 6000 的时候可以先出缓速等升级天神的时候再卖掉)...

    tanchishe.rar_4 3 2 1

    这种效果的实现可能依赖于对游戏地图的巧妙处理,通过坐标映射或者循环边界条件来确保蛇的连续移动。 第三,**结果记录**功能是游戏的一大亮点,它可以记录玩家的游戏得分和最高纪录,增加了游戏的竞争性和挑战性。...

    生命游戏代码

    4. 平衡:其他情况下(即1个或2个活邻居),细胞保持当前状态,不生不死。 在实际的代码实现中,开发者可能会使用二维数组或矩阵来存储细胞的状态,并通过遍历整个网格,检查每个细胞及其邻居的状态,根据上述规则...

    LED信赖性检验规范.docx

    2. 冷热冲击实验:样品经历(-40℃/30分钟)到(120℃/30分钟)的温度循环,实验前后检查LED是否不死灯和明显损坏。 3. 低温储存实验:在-40±2℃的环境中存放1000小时,确认LED在低温环境下不会死灯或有明显损坏。 4. ...

    Tomcat Filter类型内存马与查杀技术学习1

    4. 创建与不死马相同名字的文件或目录,以阻止其写入 如果我们将其类比到Java环境,特别是Tomcat容器,内存马的特点是无文件落地且能持续执行。在Tomcat中,实现内存马的关键在于对Listener、Filter和Servlet这三个...

    Android Service那些事1

    5. **服务常驻与不死问题**: 保持Service常驻的常见策略包括提高代码质量以防止崩溃,设置监控服务的其他Service(称为“看门狗”),或者使用第三方库。然而,Android系统为了优化性能,可能会在内存紧张时杀死...

    宁夏平罗中学2020届高三生物上学期第一次月考9月试题无答案

    7. 农业生态工程:建立沼气池提高了能量利用率,沼渣沼液回田提供养分,体现了物质循环利用。该生态工程体现了整体性原理,改善了环境。 8. 基因工程:在构建重组质粒时,使用限制性内切酶EcoRI和DNA连接酶。将目的...

    GameOfLife:康威的生命游戏模拟器

    3. 过度拥挤:一个细胞如果有4或更多邻居,则在下一轮死亡(生而复死)。 4. 死寂:一个细胞如果有2或3个邻居,则保持其当前状态(既不生也不死)。 这些规则看似简单,却能够模拟出丰富多彩的动态模式,如滑翔机、...

Global site tag (gtag.js) - Google Analytics