多線程中 堆和棧的區別


很多現代操作系統中,一個進程的(虛)地址空間大小為4G,分為系統空間和用戶空間兩部分,系統空間為所有進程共享,而用戶空間是獨立的,一般WINDOWS進程的用戶空間為2G。
  一個進程中的所有線程共享該進程的地址空間,但它們有各自獨立的(私有的)棧(stack),Windows線程的缺省堆棧大小為1M。堆(heap)的分配與棧有所不同,一般是一個進程有一個C運行時堆,這個堆為本進程中所有線程共享,Windows進程還有所謂進程默認堆,用戶也可以創建自己的堆。
堆: 是大家共有的空間,分全局堆和局部堆。全局堆就是所有沒有分配的空間,局部堆就是用戶分配的空間。堆在操作系統對進程初始化的時候分配,運行過程中也可以向系統要額外的堆,但是記得用完了要還給操作系統,要不然就是內存泄漏。
 
棧:是個線程獨有的,保存其運行狀態和局部自動變量的。 棧在線程開始的時候初始化,每個線程的棧互相獨立,因此,棧是 thread safe的操作系統在切換線程的時候會自動的切換棧,就是切換 SS/ESP寄存器。棧空間不需要在高級語言里面顯式的分配和釋放。

參考資料: 進程線程與棧 堆的關系(轉)

一篇文章:

最初涉及多線程程序涉及的時候經常會出現一些令人難以思議的事情,用堆和棧分配一個變量可能在以后的執行中產生意想不到的結果,而這個結果的表現就是內存的非法被訪問,導致內存的內容被更改。

   理解這個現象的兩個基本概念是:在一個進程的線程共享堆區,而進程中的線程各自維持自己堆棧。

另一運行機制就是如果聲明一個成員變量 如 char Name[200],隨着這段代碼調用的結束,Name在棧區的地址被釋放,而如果是 char * Name = new char[200]; 情況則完全不同,除非顯示調用delete否則 Name指向的地址不會被釋放。

   理解了線程對 堆棧 的可見性,和內存管理機制就能推測出筆者伊始提出的現象。

   用一個 實例來深入理解這種機制。

   在線程 1 中,

   A ()

   {

        B();

        C();

   }

   B()

   {

        棧 or 堆分配變量 V;

        將V的地址插入 公共隊列;

   }

   線程 2 中:

   D()

   {

       while(1)

       {

           處理公共隊列;

       }

   }

  在B中如果用棧區 即采用臨時變量的機制分配聲明V和堆區,而者的結果是不同的。如果用棧區,如果變量地址為Am1-Am2這么大,退出B調用時候這段地址被釋放,C函數可能將這段內存改寫;這樣當D執行的時候,從內存Am1-Am2中讀取的內容就是被改過的了。

  而如果用New(堆)分配,則不會出現那樣的情況,因為沒有顯示對用delete並且堆對於線程共享,即2線程可以看到1線程在堆里分配的東西,所以不會發生誤寫。

http://blog.sina.com.cn/s/blog_5c4aa6bc0100gdbm.html

更多:http://blog.csdn.net/gykimo/article/details/9132157


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM