• <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 老狼 閱讀(750) 評論(2)  編輯 收藏 引用 所屬分類: C/C++

            Feedback

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

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

            国产成人久久精品激情| 久久九九久精品国产| 亚洲国产成人久久笫一页| 国产精品九九久久免费视频 | 一本久道久久综合狠狠躁AV| 国产精品久久久久影院嫩草| 欧美亚洲色综久久精品国产| 伊人久久久AV老熟妇色| 亚洲精品美女久久久久99| 久久午夜羞羞影院免费观看| 久久夜色精品国产噜噜亚洲a| 久久男人中文字幕资源站| 久久亚洲sm情趣捆绑调教| 亚洲国产另类久久久精品黑人| 人妻精品久久无码专区精东影业 | 99久久综合狠狠综合久久止| 久久大香香蕉国产| 无夜精品久久久久久| 久久精品国产亚洲av麻豆色欲| 久久精品国产精品青草app| 欧美久久亚洲精品| 久久噜噜电影你懂的| 亚洲?V乱码久久精品蜜桃| 精品国产一区二区三区久久久狼| 国产2021久久精品| 久久99国产精品久久| 中文字幕久久精品无码| 国产精品免费看久久久香蕉| 欧美久久一区二区三区| 69久久精品无码一区二区| 性做久久久久久免费观看| 久久中文娱乐网| 久久国产乱子伦精品免费强| 久久人妻少妇嫩草AV蜜桃| 国产精品久久久久久| 亚洲熟妇无码另类久久久| 久久只有这精品99| 久久人人爽人人爽人人片AV麻烦| 99久久精品国产一区二区| 精品久久久久香蕉网| 久久精品成人欧美大片|