簡單分析針對ARM平臺的C語言程序的編譯問題
我們知道在C語言編譯時(shí),有那么幾個(gè)常用的優(yōu)化編譯選項(xiàng),分別是-O0,-O1,-O2,-O3以及-Os。之前一直覺得既然是優(yōu)化選項(xiàng),頂多是優(yōu)化一下邏輯,提高一些效率或者減少一下程序大小而已。很少會(huì)覺得它們會(huì)影響程序的最終結(jié)果。直到最近在ARM平臺上發(fā)現(xiàn)一個(gè)程序里的一個(gè)bug,才覺得這些優(yōu)化選項(xiàng)有時(shí)候也沒那么智能?;蛘哒f針對ARM平臺,還沒有那么智能。
首先看這么一段程序,此程序是我將問題簡單化的程序:
#include<stdio.h> #include<string.h> int main() { char buffer[1024] = {0,1,2,3,4,5,6,7}; int iTest = 0x12345678; int *p = (int *)(buffer + 7); memcpy(p, &iTest, sizeof(iTest)); printf("%x\n", buffer[6]); printf("%x\n", buffer[9]); return 0; }
乍看之下,覺得這個(gè)程序沒啥問題。然后我們將此程序文件名稱叫point.c。然后分別用交叉編譯鏈進(jìn)行如下編譯:
arm-xxx-linux-gcc point.c -o point0 -O0 arm-xxx-linux-gcc point.c -o point1 -O1 arm-xxx-linux-gcc point.c -o point2 -O2
最終再分別執(zhí)行三個(gè)程序,結(jié)果卻有點(diǎn)出人意料:
./point0 6 34 ./point1 34 0 ./point2 6 0
只有在-O0,也就是沒有優(yōu)化的情況下,結(jié)果才和假想的一致。但是同樣的問題在x86平臺上卻沒有問題。
于是我通過用以下命令,分別來生成不同優(yōu)化選項(xiàng)下的匯編代碼,來確定在ARM平臺上編譯到底出了什么問題。
arm-xxx-linux-gcc point.c -o point0.s -O0 -S arm-xxx-linux-gcc point.c -o point1.s -O1 -S arm-xxx-linux-gcc point.c -o point2.s -O2 -S
然后對比三個(gè)匯編的代碼,發(fā)現(xiàn)問題出在memcpy這句話上。
在point0.s中,程序是老老實(shí)實(shí)的調(diào)用的memcpy,然后就將0x12345678老老實(shí)實(shí)按照字節(jié)一個(gè)個(gè)的放到了buffer+7的位置。
而在point1.s中程序則是沒有調(diào)用memcpy,而是用的語句:
str r3, [sp, #7]
而此時(shí)r3中存儲的就是0x12345678;而由于我采用的ARM平臺是32位的,此語句執(zhí)行時(shí),地址線應(yīng)該不會(huì)發(fā)生變化,所以最終的結(jié)果是buffer+4到buffer+7的數(shù)據(jù)被覆蓋了,而不是buffer+7到buffer+10的數(shù)據(jù)被修改。
而在point2.s中,貌似又針對流水線進(jìn)行了優(yōu)化,程序執(zhí)行順序會(huì)有所變化,在對buffer部分位置賦初值的順序是在str r3, [sp, #7]之后,所以buffer+6處的數(shù)據(jù)反而是正確的6。
分析到這兒,也許有人會(huì)說寫個(gè)簡單的程序,都會(huì)因?yàn)榫幾g的優(yōu)化選項(xiàng)不同導(dǎo)致結(jié)果不同,那這memcpy是不是就不敢用了?
其實(shí)一般只要有較好的編程習(xí)慣的話,都不會(huì)遇到此類問題,比如下面的程序:
#include<stdio.h> #include<string.h> int main() { char buffer[1024] = {0,1,2,3,4,5,6,7}; int iTest = 0x12345678; char *p = buffer + 7; memcpy(p, &iTest, sizeof(iTest)); printf("%x\n", buffer[6]); printf("%x\n", buffer[9]); return 0; }
這段程序其實(shí)只是簡單的改變了p的類型,就能保證在各種優(yōu)化下,結(jié)果都一樣。可見好的編程習(xí)慣是有多么的重要。
上一篇:C++中的按位與&、按位與或|、按位異或^運(yùn)算符詳解
欄 目:C語言
下一篇:C++語言編寫寫日志類
本文標(biāo)題:簡單分析針對ARM平臺的C語言程序的編譯問題
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/2597.html
您可能感興趣的文章
- 01-10HDOJ 1443 約瑟夫環(huán)的最新應(yīng)用分析詳解
- 01-10c++中inline的用法分析
- 01-10深入理解堆排序及其分析
- 01-10基于C程序啟動(dòng)代碼的深入分析
- 01-10深入分析父子線程、進(jìn)程終止順序不同產(chǎn)生的結(jié)果
- 01-10基于C語言指令的深入分析
- 01-10基于C++輸出指針自增(++)運(yùn)算的示例分析
- 01-10深入分析C中不安全的sprintf與strcpy
- 01-10c 調(diào)用python出現(xiàn)異常的原因分析
- 01-10C 轉(zhuǎn)移表/轉(zhuǎn)換表的深入分析


閱讀排行
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對數(shù)函數(shù)的表達(dá)式 c語言中對
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
隨機(jī)閱讀
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 08-05織夢dedecms什么時(shí)候用欄目交叉功能?
- 01-10C#中split用法實(shí)例總結(jié)
- 01-10使用C語言求解撲克牌的順子及n個(gè)骰子
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 04-02jquery與jsp,用jquery
- 01-11ajax實(shí)現(xiàn)頁面的局部加載
- 01-10delphi制作wav文件的方法
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改