防止C语言编译器生成不正确的可执行程序

C语言程序编写完成后,我们会使用C编译器对其进行处理,生成可执行文件。

为了让软件运行更加高效,现在的C语言编译器在生成可执行文件时,常常进行优化,这个时候就有可能生成不正确的可执行文件。


下面举一个例子来说明。

源代码

<code>#include 
void main()
{
    int iValue1;
    int iValue2 = 10;
    int iValue3 = iValue2;
    int* piValue = &iValue1;
    piValue++;
    *piValue = 20;
    iValue1 = iValue2;
    printf("iValue1: %d, iValue2: %d, iValue3: %d\n", iValue2, iValue2, iValue3);
}/<code>

代码的含义是:

(1)给iValue2赋值为10;

(2)将iValue2的值赋给iValue3;

(3)给iValue2赋值为20;

(4)将iValue2的值赋给iValue1;

(5)打印iValue1、iValue2、iValue3的值。


说明一下,这里故意在第二次给iValue2赋值时,将代码写得比较隐晦(piValue++其实就是iValue2的指针),用于骗过编译器。


代码编译时不优化,生成了正确的可执行文件

编译命令

<code>gcc -O0 volatile.c -o volatile/<code>

运行程序

<code>./volatile
iValue1: 20, iValue2: 20, iValue3: 10/<code>

结论:当代码编译不优化时,程序正常运行。


代码编译时优化,生成了错误的可执行文件

编译命令

<code>gcc -O1 volatile.c -o volatile/<code>

运行程序

<code>./volatile 
iValue1: 10, iValue2: 10, iValue3: 10/<code>

结论:当代码编译优化时,程序运行结果出错。


原因分析

程序被优化方式编译时,编译器发现piValue的值没有被使用,因此将所有piValue相关的代码,全部删除了,导致结果出错。


解决方法:在被优化的变量前加上volatile限定符

英语单词volatile的含义是“易变的”。

C语言中,变量前面的volatile限定符,也是用来告诉编译器,这个变量的值容易改变,有可能在其他地方被不可预测地改变,这样编译器就不会对其进行编译优化。


对于上面的例子,将iValue2、piValue分别加上volatile修饰符,即使使用优化编译方式,也不会生成错误的可执行文件。

<code>#include 
void main()
{
    int iValue1;
    volatile int iValue2 = 10;
    int iValue3 = iValue2;
    volatile int* piValue = &iValue1;
    piValue++;
    *piValue = 20;
    iValue1 = iValue2;
    printf("iValue1: %d, iValue2: %d, iValue3: %d\n", iValue2, iValue2, iValue3);
}/<code>


谢谢您的阅读!


分享到:


相關文章: