GCC優化與返回Local Variables

GCC優化與返回值

1 GCC優化與返回局部變量(Local variables)

1.1 實驗環境:debian6, gcc 4.4.5

1.2 進入正題:

先看代碼:

char*  func(int a)
{
   char xxxx[ 20 ] = "func test return";

   return xxxx;
}
//爲了節約版面,這裏省略main函數的代碼

趕緊很明顯是錯誤的,返回棧上的局部變量。函數返回的時候變量已經不存在了!這樣編譯:

gcc xxx.c
有如下警告信息:
return.c: In function ‘func’:
return.c:21: warning: function returns address of local variable

返回結果“打印”是正確的!當然我還是懷疑結果的正確性!再寫測試代碼如下:

char*  func(int a)
{
   char xxxx[ 20 ] = "func test return";

   return xxxx;
}

char*  func1(int a)
{
   char *xxxx="func1 test return";

   return xxxx;
}

int main(int argc, char *argv[])
{
   char *ptr = func(100 );
   printf( "first  = %s\n", ptr);
   printf( "%s\n", func1(90 ));
   printf( "second = %s\n", ptr);
   
   return 0;
}

這個測試用列是有特別用意的,調用函數func和func1的棧結構是一樣的。結果輸出是錯誤的!爲什麼呢?其實想象也是明白的,函數調用肯定是不會出錯,只是返回了棧上的地址而已,操作返回的地址纔會出錯。這也是指針的特性!說到這裏是否和GCC優化還是沒有扯傻瓜關係,下面我們加入優化選項觀察!這樣編譯:

gcc -O3 xxx.c
有如下警告信息:
return.c: In function ‘func’:
return.c:21: warning: function returns address of local variable

返回結果是正確的!對比兩總編譯方式的彙編:第一種:

0000000000400534 <func>:
  400534:       55                      push   %rbp
  400535:       48 89 e5                mov    %rsp,%rbp
  400538:       89 7d dc                mov    %edi,-0x24(%rbp)
  40053b:       c7 45 e0 66 75 6e 63    movl   $0x636e7566,-0x20(%rbp)
  400542:       c7 45 e4 20 74 65 73    movl   $0x73657420,-0x1c(%rbp)
  400549:       c7 45 e8 74 20 72 65    movl   $0x65722074,-0x18(%rbp)
  400550:       c7 45 ec 74 75 72 6e    movl   $0x6e727574,-0x14(%rbp)
  400557:       c7 45 f0 00 00 00 00    movl   $0x0,-0x10(%rbp)
  40055e:       48 8d 45 e0             lea    -0x20(%rbp),%rax
  400562:       c9                      leaveq
  400563:       c3                      retq

第二種:

0000000000400540 <func>:
   400540:       48 8d 44 24 d8          lea    -0x28(%rsp),%rax
   400545:       c3                      retq   
   400546:       66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
   40054d:       00 00

第二種直接把函數inline了,所以打印的結果是正確的!

1.3 總結

1.3.1 一定要儘量解決編譯時的警告

一定要解決加上-Wall -Wextra編譯選項以後產生的警告。不解決的前提是警告確實你需要的語義!像上面的返回局部變量是有警告提示的,如果解決就可以避免這樣的錯誤。

1.3.2 要與項目的構建環境保持一致和獨立性

當然也就是一致測試和分離測試。假如構建環境中默認是加了-O3。就不會即使發現這樣的問題。這就需要分離測試解決,但是話說回來比較好的構建環境因該要同時解決這兩個問題。

Author: OCaml<[email protected]>

Date: 2012-05-08 11:14:49 CST

HTML generated by org-mode 6.33x in emacs 23

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章