欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

簡單分析針對ARM平臺的C語言程序的編譯問題

 更新時間:2015年12月10日 17:47:02   作者:守夜者  
這篇文章主要介紹了針對ARM平臺的C語言程序的編譯問題,從優(yōu)化編譯選項的幾個方面進行分析,需要的朋友可以參考下

  我們知道在C語言編譯時,有那么幾個常用的優(yōu)化編譯選項,分別是-O0,-O1,-O2,-O3以及-Os。之前一直覺得既然是優(yōu)化選項,頂多是優(yōu)化一下邏輯,提高一些效率或者減少一下程序大小而已。很少會覺得它們會影響程序的最終結(jié)果。直到最近在ARM平臺上發(fā)現(xiàn)一個程序里的一個bug,才覺得這些優(yōu)化選項有時候也沒那么智能?;蛘哒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;
}

乍看之下,覺得這個程序沒啥問題。然后我們將此程序文件名稱叫point.c。然后分別用交叉編譯鏈進行如下編譯:

 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í)行三個程序,結(jié)果卻有點出人意料:

 ./point0
 6
 34
 ./point1
 34
 0
 ./point2
 6
 0

    只有在-O0,也就是沒有優(yōu)化的情況下,結(jié)果才和假想的一致。但是同樣的問題在x86平臺上卻沒有問題。
    于是我通過用以下命令,分別來生成不同優(yōu)化選項下的匯編代碼,來確定在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

    然后對比三個匯編的代碼,發(fā)現(xiàn)問題出在memcpy這句話上。
    在point0.s中,程序是老老實實的調(diào)用的memcpy,然后就將0x12345678老老實實按照字節(jié)一個個的放到了buffer+7的位置。
    而在point1.s中程序則是沒有調(diào)用memcpy,而是用的語句:
    str        r3, [sp, #7]
    而此時r3中存儲的就是0x12345678;而由于我采用的ARM平臺是32位的,此語句執(zhí)行時,地址線應(yīng)該不會發(fā)生變化,所以最終的結(jié)果是buffer+4到buffer+7的數(shù)據(jù)被覆蓋了,而不是buffer+7到buffer+10的數(shù)據(jù)被修改。
    而在point2.s中,貌似又針對流水線進行了優(yōu)化,程序執(zhí)行順序會有所變化,在對buffer部分位置賦初值的順序是在str  r3, [sp, #7]之后,所以buffer+6處的數(shù)據(jù)反而是正確的6。
    分析到這兒,也許有人會說寫個簡單的程序,都會因為編譯的優(yōu)化選項不同導(dǎo)致結(jié)果不同,那這memcpy是不是就不敢用了?
    其實一般只要有較好的編程習(xí)慣的話,都不會遇到此類問題,比如下面的程序:

#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;
}

    這段程序其實只是簡單的改變了p的類型,就能保證在各種優(yōu)化下,結(jié)果都一樣??梢姾玫木幊塘?xí)慣是有多么的重要。

相關(guān)文章

  • C++編程中的格式化輸出詳解

    C++編程中的格式化輸出詳解

    這篇文章主要介紹了C++編程中的格式化輸出詳解,是C++入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
    2015-09-09
  • C語言鏈表實現(xiàn)學(xué)生成績管理系統(tǒng)

    C語言鏈表實現(xiàn)學(xué)生成績管理系統(tǒng)

    這篇文章主要為大家詳細介紹了C語言鏈表實現(xiàn)學(xué)生成績管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • C語言中無符號數(shù)和有符號數(shù)之間的運算

    C語言中無符號數(shù)和有符號數(shù)之間的運算

    C語言中有符號數(shù)和無符號數(shù)進行運算默認會將有符號數(shù)看成無符號數(shù)進行運算,其中算術(shù)運算默認返回無符號數(shù),邏輯運算當然是返回0或1了。下面通過一個例子給大家分享C語言中無符號數(shù)和有符號數(shù)之間的運算,一起看看吧
    2017-09-09
  • C語言鏈表實現(xiàn)商品庫存管理系統(tǒng)

    C語言鏈表實現(xiàn)商品庫存管理系統(tǒng)

    這篇文章主要為大家詳細介紹了C語言鏈表實現(xiàn)商品庫存管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • 詳解Qt中的雙緩沖機制與實例應(yīng)用

    詳解Qt中的雙緩沖機制與實例應(yīng)用

    所謂雙緩沖機制,是指在繪制控件時,首先將要繪制的內(nèi)容繪制在一個圖片中,再將圖片一次性地繪制到控件上。本文主要為大家介紹了Qt中的雙緩沖機制與實例應(yīng)用,希望對大家有所幫助
    2023-03-03
  • 詳解C++中future和promise的使用

    詳解C++中future和promise的使用

    future和promise的作用是在不同線程之間傳遞數(shù)據(jù),這篇文章主要為大家詳細介紹了C++中future和promise的具體使用,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-05-05
  • C++中指向?qū)ο蟮某V羔樑c指向常對象的指針詳解

    C++中指向?qū)ο蟮某V羔樑c指向常對象的指針詳解

    如果一個變量已經(jīng)被聲明成常變量,則只能用指向常變量的指針變量指向它,而不能用一般的(非const型的)指針變量指向它
    2013-10-10
  • C++實現(xiàn)哈夫曼樹簡單創(chuàng)建與遍歷的方法

    C++實現(xiàn)哈夫曼樹簡單創(chuàng)建與遍歷的方法

    這篇文章主要介紹了C++實現(xiàn)哈夫曼樹簡單創(chuàng)建與遍歷的方法,對于C++算法的學(xué)習(xí)來說不失為一個很好的借鑒實例,需要的朋友可以參考下
    2014-07-07
  • 詳解C++ 動態(tài)內(nèi)存分配與命名空間

    詳解C++ 動態(tài)內(nèi)存分配與命名空間

    這篇文章主要介紹了詳解C++ 動態(tài)內(nèi)存分配與命名空間,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-08-08
  • C++實現(xiàn)LeetCode(45.跳躍游戲之二)

    C++實現(xiàn)LeetCode(45.跳躍游戲之二)

    這篇文章主要介紹了C++實現(xiàn)LeetCode(45.跳躍游戲之二),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-07-07

最新評論