C++跨DLL内存所有权问题探幽(二)CRT中MT和MD混用导致的堆损坏
0xC0000374: 堆已損壞。 (參數: 0x00007FFA1E9787F0)。
_Mem 是 nullptr
我在開發的過程中有遇到上面兩個東西的bug,百思不得其解,最后才發現這個和兩個DLL中的MT和 MD選項有關系。
具體情境時:我在一個MT編譯的DLL A中引用了一個MD編譯的DLL B,并且在A的頭文件中聲明了一個B對象,這段代碼在使用的過程中產生了所有權問題,導致了上述的兩個問題。
在正式討論這個問題之前,需要做一些知識儲備
什么是MD和MT編譯?
在C++中,MD(Multi-threaded DLL)和MT(Multi-threaded)是Microsoft Visual C++編譯器提供的不同的運行時庫選項。它們在處理線程、內存管理和鏈接方式上有所不同。
Multi-threaded DLL(MD):
相當于在編譯的時候不將DLL依賴的DLL放在其內部。
MD選項意味著您的應用程序將使用動態鏈接的多線程C/C++運行時庫(CRT)。這意味著您的應用程序將與系統共享這些運行時庫。這可以減少最終生成的可執行文件的大小,因為它們不會包含整個運行時庫的副本。
運行時庫的版本由操作系統決定。如果系統中已經安裝了相應版本的運行時庫,那么您的應用程序將可以共享這些庫,而不需要額外的安裝。
Multi-threaded(MT):
相當于在編譯的時候將DLL依賴的DLL放在其內部。
MT選項意味著您的應用程序將使用靜態鏈接的多線程C/C++運行時庫(CRT)。這意味著您的應用程序將包含完整的運行時庫的副本,因此可能會增加最終生成的可執行文件的大小。
運行時庫會隨著應用程序一起分發,因此用戶在運行應用程序之前不需要安裝任何其他組件。
這些運行時庫負責處理諸如內存管理、線程管理、異常處理和其他與C/C++編程相關的任務。它們提供了諸如動態內存分配和釋放、線程同步機制、異常處理等功能。選擇使用哪種運行時庫取決于項目的需求,以及對最終可執行文件大小和依賴性的要求。選擇不同的運行時庫可能會影響應用程序的性能和行為。
關于DLL引用
書接上文C++跨DLL內存所有權問題探幽(一)DLL提供的全局單例模式
我們知道一個程序有堆棧啊這些內存空間。
在C++開發中,堆空間和棧空間是用來存儲變量和對象的兩個主要內存區域。當一個進程引用一個DLL(動態鏈接庫)時,在頭文件中聲明一個對象和聲明一個指針有一些關鍵區別:
- 對象聲明:
如果您在頭文件中聲明一個對象,它將分配在棧空間中。這意味著對象的生命周期將受限于其所在的作用域。當對象所在的作用域結束時,對象將被自動銷毀并釋放其占用的內存。
如果對象是在動態鏈接庫中定義的,那么在引用動態鏈接庫的程序中,對象的定義和實現將被復制到主程序中。這可能會導致重復定義的問題。
- 指針聲明:
如果您在頭文件中聲明一個指針,它將分配在棧空間中。但是指針所指向的對象可能分配在堆空間中,特別是如果您在動態鏈接庫中使用new關鍵字來動態分配內存。
通過使用指針,您可以在程序中傳遞對象的引用而不是實際的對象本身。這使得對象可以在堆上動態分配,并且可以在不同的模塊之間共享。
也就是說
為什么崩潰?
當在C++中混用MD(Multi-threaded DLL)和MT(Multi-threaded)的DLL時,可能會導致內存沖突和崩潰的主要原因在于堆棧空間的所有權問題。
對堆空間而言
對于MD編譯的DLL,它使用的是共享的動態鏈接的多線程C/C++運行時庫,這意味著它使用了操作系統提供的堆管理機制來分配和釋放內存。如果您在MD編譯的DLL中分配了一塊堆內存,它實際上是由操作系統的運行時庫進行管理的。
對于MT編譯的DLL,它使用的是靜態鏈接的多線程C/C++運行時庫,這意味著它會包含自己的堆管理機制。如果您在MT編譯的DLL中分配了一塊堆內存,它將由該DLL的運行時庫管理。
棧空間:
棧空間的所有權歸屬于當前線程。當您在MD和MT編譯的DLL之間切換時,棧空間的所有權可能會發生變化。如果一個線程在MD編譯的DLL中分配了一塊棧內存,然后在MT編譯的DLL中嘗試釋放它,或者反之亦然,就會產生內存沖突,導致不可預測的行為和可能的崩潰。
因此,在混用MD和MT編譯的DLL時,由于堆空間和棧空間的所有權歸屬和管理方式不同,可能會導致內存的沖突。這種沖突可能會引起一系列問題,包括內存泄漏、指針懸空、數據損壞等,最終導致程序崩潰或產生不可預測的行為。為避免這種情況,請確保在整個應用程序中使用相同類型的運行時庫編譯所有的DLL。
參考:MD(d)、MT(d)編譯選項,在使用Release編譯的話不會觸發這個崩潰問題。
總結
以上是生活随笔為你收集整理的C++跨DLL内存所有权问题探幽(二)CRT中MT和MD混用导致的堆损坏的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Rs1805007影响人体对麻醉药的敏感
- 下一篇: 栈和括号匹配,一文搞懂