防止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>


謝謝您的閱讀!


分享到:


相關文章: