• <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>
            淺談C++中的內存管理
            摘要:

            大家都知道變量的生存周期這個概念,可是有的時候命名生存周期已經結束,但是所分配的那塊內存空間還是存在的。文章舉了四個不同的例子,來說明這其中的原因。

            前言:

            前一段時間在一個好友的的博客論壇上看到他學習C++時遇到的一小點問題,是關于C++中最基本的內存分配方面的。其實對于內存這東西,除了知道我自己用的是256M的內存以外,我也不太清楚他到底里面是怎么工作的。看了大師們的講解,我深有體會,把這些講解整理出來,為所有C++的newbie們共勉!

            正文:

            事情是因為這樣一小段程序而來的。

            int main()
            {
              int i=10;
              int *j=&i;
              if(!0)
              {
                int l=20;
                int *k=&l;
                j=k;
                k=0;
              }
              cout<<*j;
              return 0;
            }


            不用編譯器,大家想想執行過之后應該打印什么結果?我想大家的第一反應應該是打印出一個不確定的數。理由是在if語句里,我們定義了k這個變量,在if執行結束之后,這個變量k所占據的內存是被系統收回的,于是也就造成了變量j所指的結果非常不確定。當然,如果編譯并且執行過后,我們發現事情并不是像我們想象的那樣,程序最終的打印結果是20,并不是我們期待的一個不確定的數。下面就讓我們分析一下原因吧!

            我們用debug的方式來一步一步的分析,在watch的窗口下輸入里面所有的變量。

            int i=10;  //i is 10 and &i is 0x0012ff7c
            int *j=&i; //*j is 10 and &j is 0x0012ff7c
                  //顯然可以看出此時兩個變量指的是同一地址
            if(!0)
            {
              int l=20; //l is 20 and &l is 0x0012ff74

              /*地址0x0012ff7c—0x0012ff75被占據。要說明的是,
              這個數值很有可能因為電腦硬件的不同而不同。*/

              int *k=&l; //*k is 20 and &k is 0x0012ff74

              //變量k與l指向同一地址。

              j=k;  //j is 0x0012ff74 and *j is 20

              /*指針間的賦值,這個語句的意思是把k指向的地址負值給j。
              此時這兩個變量指向的是同一個地址,都是0x0012ff74,而那
              塊地址存放的是20,所以也就有*j是20的原因。*/
            }

            cout<<*j; //*j is 20 and j is 0x0012ff74

            /*此時同時可以看到k的地址是0x00000000,說明k這個變量
            已經被自動銷毀,所以地址指零。但是j所指的并不是k,而
            是k所指的那段地址0x0012ff74,而由于此時j的生存周期還
            沒有結束(j是在if意外定義的),所以j指向的這塊地址并
            沒有被收回,也就保存下來20這個數了。*/


            至此,我們分析完了程序的全過程的內存分配情況,最終結果是這樣的。(圖1)
            無標題.JPG

            我們同時也可以在Memory里面看看這個地址的具體內容。我們可以看到是14,這是十六進制的數,化成十進制,正好是20。(圖2)
            無標題2.JPG

            現在大家應該對上面那個程序的執行過程有一個大概地了解了吧!不過這個還不是我們想要得到的結果,我們需要的是打印一個不確定的結果。有了以上的分析,我們開始新的程序,讓他打印出我們想要的東西。

            對于上面的程序,我們需要改動的是令變量j指向一個地址被釋放的位置。于是就有了下面的程序。

            int * foo()
            {
              int l=20;
              return &l;
            }

            int main()
            {
              int i=10;
              int *j=&i;
              j = foo();
              cout<<*j;
              return 0;
            }

            編譯器很“聰明”,編譯后會給出一個警告。原話是“returning address of local variable or temporary”,指向的是上面程序的第四行,也就是return &l;這條語句。那句英文的意思也不用我再多解釋了,相信大家都能看得明白。

            執行的結果,在debug下,是20;在release下,結果是4198795。顯然那部分內存被釋放掉了。這是因為在debug的程序里面,執行完函數foo,并沒有立即釋放掉l的那個地址(目前我不清楚這句話說得是否精確)。在這個程序的release版本中,顯然程序釋放了那部分的地址,所以指向了一個不確定的數。

            這里還要說一件事情,就是在第一個程序當中,無論是debug版本還是release版本。執行完那個if語句以后,系統都是不會真正的把l清除掉,l只是k的一個別名。上面的程序是這樣寫的,用了*j=&i這樣一句負值語句,而別名在MSDN中的解釋與引用是相同的,所以也可以這樣理解,int i=10; int &j=i;與上面的相同。不要去想上面這些程序了,大家再看看下面這個。

            void f1( int *& j)
            {
              int l=20;
              int *k=&l;
              j=k;
              k=0;
            }

            void any_function_use_local_variables()
            {
              int a,b,c;
              a=b=c=100;
            }

            int main()
            {
              int i=10;
              int *j=&i;
              f1(j);
              cout<<*j;
              any_function_use_local_variables();
              cout<<*j;
              return 0;
            }


            請大家自己編譯、執行,看看結果是什么,然后結合上面的兩個例子,想想是為什么。下面再給大家一個小例子,可能會有助于理解內存的概念。

            程序的過程是試圖去增加i,使之超過最大的整數。有一種情況是這個值被“卷回來”變成一個負數,在我的機器上程序的打印結果是-2147483648,這個結果可能因為硬件的不同而不同。

            int main()
            {
              int i=1;
              while(0<i) i++;
              cout<<i;
              return 0;
            }

            結束:

            其實我對于內存的理解也是極為有限的。討論這個問題的原帖子在這里。里面回答問題的全都是Microsoft MVP或者是準MVP,我也是從那里學習過來的。希望大家能從我的這篇文章中受益。這樣,也就達到了我寫文章的目的。:P

            了解更多詳情,參與討論,請進入GBUNIX論壇

            http://www.gbunix.com/bbs/forums.html


            Posted on 2005-11-11 12:15 艾凡赫 閱讀(340) 評論(0)  編輯 收藏 引用 所屬分類: C++
            9191精品国产免费久久| 欧美一区二区三区久久综合| 国产情侣久久久久aⅴ免费| 成人久久精品一区二区三区| 青青热久久综合网伊人| 亚洲欧洲久久av| 精品999久久久久久中文字幕| 欧美久久久久久午夜精品| 性色欲网站人妻丰满中文久久不卡| 久久91精品久久91综合| 欧美国产成人久久精品| 久久久久久久久久免免费精品 | 无码精品久久一区二区三区 | 久久久久久精品免费看SSS| 99久久婷婷免费国产综合精品| 午夜视频久久久久一区 | 国产Av激情久久无码天堂| 亚洲精品无码久久不卡| 国产精品久久久99| 久久无码av三级| 日本精品久久久久中文字幕8| 久久精品国产精品亚洲毛片| 中文字幕乱码人妻无码久久| 婷婷久久综合| 狠狠色丁香婷婷久久综合| 久久精品免费网站网| 精品国产91久久久久久久a| 久久精品免费观看| 99久久精品国产免看国产一区| 久久精品国产2020| 亚洲中文久久精品无码ww16| 中文字幕乱码人妻无码久久| 久久久久久综合网天天| 久久久久99这里有精品10| 2021国产精品午夜久久| 久久久久久精品无码人妻| 亚洲精品无码专区久久久| 无码伊人66久久大杳蕉网站谷歌| 亚洲精品无码专区久久久 | 国产精品久久久久久| 久久九九青青国产精品|