• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            Mike's blog

              C++博客 :: 首頁 :: 聯系 :: 聚合  :: 管理
              0 Posts :: 23 Stories :: 83 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(17)

            我參與的團隊

            搜索

            •  

            最新評論

            先看一個例子:
             1#include <stdio.h>
             2#include <stdlib.h>
             3#include <string.h>
             4
             5char* fun(const char* src)
             6{
             7  static char dest[32= "";
             8  
             9  strcpy(dest, src);
            10
            11  return dest;
            12}

            13
            14int main()
            15{
            16  char s1[32= "";
            17  char s2[32= "";
            18
            19  strcpy(s1, fun("hello"));
            20  strcpy(s2, fun("world"));
            21
            22  printf("%s %s\n", s1, s2);
            23  printf("%s %s\n", fun("hello"), fun("world"));
            24
            25  return 0;
            26}

                讀一下這個程序,先看這個程序寫的有問題沒(假設fun函數的參數長度小于32)?如果你對這個程序中的fun函數返回一個局部變量的數組產生了疑問,那么我希望你是沒注意到我使用的static類型,若你仍有疑問,建議你先回去查查static變量的作用域和生命周期的概念。
                OK,是運行這個程序的時候了,看一下運行結果是否跟你想象的一樣呢?如果是一樣的,那么這篇文章你不用看了,因為你已經掌握了我下面要說的問題了。好吧,對于不理解運行結果的朋友,我們來分析一些下面那個printf語句,首先要知道printf中的表達式、函數的執行順序是至右向左的,也就是先執行了fun("world")返回了dest的地址,然后再執行fun("hello")也返回了dest的地址,而這兩次返回的dest用的同一塊地址(因為是static類型),也就是第二次的執行覆蓋了第一次執行的結果,對dest地址進行了重新的賦值,所以結果就是打印兩個hello了。


                我們在寫C/C++程序的時候,經常需要從調用函數中取得自己想要的數據,這就需要調用者和函數之間要有個內存的交互,我們通常采用的方法是傳遞一個指針給被調函數,作為被調函數的輸出參數,這也是我們常用的、規范的做法。
                但有很多程序員比較習慣直接取返回值,這就面臨一個問題就是普通局部變量都是在棧上分派的,會隨著函數的結束而彈棧釋放,那么就會出現返回局部變量數組的問題,這時有人會想到用malloc或new在堆上分派內存,沒錯,這樣是避免了前面說的問題,但這樣又會帶來新的問題,就是需要在外部對這塊內存進行釋放,這個是比較難把握的,多次釋放會出現程序的crash,忘記釋放了會出現內存leak,所以這種方法也不被推薦。還有人想到了更另類的方法,就是上面例子中的static類型,沒錯,static變量也是全局的,但就會出現上面程序的運行結果(可以認為不是我們想要的結果,也就是錯誤的結果)。
                所以,我們要慎用返回函數內部的static內存的這種設計,但如果在無法改變設計模式的情況下(有些系統函數的實現,比如inet_ntoa,可以通過在man手冊中看到這樣的一句話:The string is returned in a statically allocated buffer, which subsequent calls will overwrite),那么在自己使用的時候一定要注意,不要試圖保存返回的內存地址或引用,而要保存返回內存的內容,也就是例子程序中的strcpy兩行。

            inet_ntoa的錯誤使用(判斷兩個IP地址是否相等):

             1struct in_addr addr1;
             2struct in_addr addr2;
             3
             4// 網絡包中包含了源地址
             5addr1.s_addr = 0x6500A8C0 // 192.168.0.101
             6addr2.s_addr = 0x6600A8C0 // 192.168.0.102
             7
             8// 這個if語句將永遠為真
             9if (strcmp(inet_ntoa(addr1), inet_ntoa(addr2)) == 0{
            10  // do something
            11}
             else {
            12  // do other thing
            13}
            posted on 2008-11-25 15:06 老狼 閱讀(756) 評論(2)  編輯 收藏 引用 所屬分類: C/C++

            Feedback

            # re: 返回static內部變量的陷阱[未登錄] 2008-11-27 15:05 小兵
            學習了  回復  更多評論
              

            # re: 返回static內部變量的陷阱 2009-01-07 12:18 July
            很好的文章,謝謝分享  回復  更多評論
              

            午夜精品久久久久久影视riav| 久久香蕉综合色一综合色88| 亚洲成av人片不卡无码久久| 色8激情欧美成人久久综合电| 久久乐国产综合亚洲精品| 天天做夜夜做久久做狠狠| 亚洲AV无码久久寂寞少妇| 久久精品国产亚洲AV香蕉| 99久久国产综合精品网成人影院| 久久综合五月丁香久久激情| 亚洲精品无码专区久久久| 亚洲精品高清国产一久久| 国产精品久久久久久久app| 精品熟女少妇av免费久久| 久久婷婷五月综合97色直播| 精品熟女少妇av免费久久| 久久人人爽人人人人片av| 久久精品视频免费| 无码专区久久综合久中文字幕| 久久久久这里只有精品| 久久精品免费观看| 国产亚洲综合久久系列| 久久天天躁夜夜躁狠狠| 天天影视色香欲综合久久| 青草影院天堂男人久久| 久久精品中文闷骚内射| 亚洲午夜久久久久久噜噜噜| 日韩美女18网站久久精品| 国产亚洲精久久久久久无码AV| 国内精品久久久久影院日本| 一本色道久久综合狠狠躁| 欧美一区二区久久精品| 亚洲成av人片不卡无码久久| 久久久久一本毛久久久| 久久久久久国产a免费观看不卡 | 国产精品激情综合久久| 99久久99久久| 久久久久夜夜夜精品国产| 久久精品www人人爽人人| 国产婷婷成人久久Av免费高清| 久久久久亚洲AV无码网站|