Golden Blonde 发表于 2017-6-20 09:49:37

一个隐晦的死循环

ULONG i,c=0;for(i=0;i<0xFFFFFFFF;i+=4096){c++;}printf("%ld\n",c);用来做代码混淆不错。:lol
死循环的原因是溢出了。

0xAA55 发表于 2017-6-21 14:03:41

此处安利C语言关键词volatile
因为编译器似乎不认为你这个会导致死循环,觉得就是“循环N次却啥也不做”的“无用语句”,就擅自帮你优化掉了。
很多情况下,你只是给一个变量赋值,但其实这个变量(或者说是寄存器)可能会被其它线程或者外部设备读取,因此这些操作是不应该被优化掉的。
对于此类变量,你就需要使用volatile关键词来修饰。如上所述代码,你把ULONG i改成volatile ULONG i或者ULONG volatile i的话,编译器生成的指令就会真的给i不停地加上4096,然后造成死循环。
有的编译器就算被你关掉了优化,它也会优化掉这些指令。

此外还有volatile修饰指针,这里存在以下几种情况:
int *i; // int类型的指针
int volatile *i; // volatile int类型的指针
volatile int *i; // 同上
int *volatile i; // int类型的,volatile的指针(很少见,我能想到的场合,也只有多线程操作的时候拿N个线程一起修改一个指针或者使用一个指针)
volatile int *volatile i; // volatile int类型的volatile指针,这个会有人用?控制一个随时会变化的指针,读取一个随时会变化的数值。
int volatile *volatile i; // 同上。

带volatile特性的变量都具有不会被编译器轻易优化掉的特性。多线程开发的时候原子操作的时候非常依赖它。

Ayala 发表于 2017-6-21 15:58:49

上面的不是空循环,也是不会被优化掉的,除非输出函数被重定义为什么都不做

Ayala 发表于 2017-6-21 16:27:59

本帖最后由 Ayala 于 2017-6-21 17:03 编辑

其实上面几种的volatile 用法都是一致的
typename volatile name


多线程中用的很多的 操作系统中也一样 dma
比如gdt idt kpcr等等都属于可变的指针 而且指针可变内部数据大多可变!

为了方便安全直接申请内存设置数据重新修改指针就可以 如果直接修改数据需要多个lock或者屏蔽中断设置锁等等 但是改指针就方便多了
指针易变一般是这样



//但是指针易变写起代码的时候会存在差异性问题
typename * a = p;
a->x1;
a->x2;

//与
p->x1;
p->x2;
//两种情况在不同场合有不同的需要

55AA 发表于 2017-10-9 18:04:56

遇到过优化的问题,当时不知道这个,感觉很奇怪
页: [1]
查看完整版本: 一个隐晦的死循环