在Linux上,我從靜態庫中生成了一些C++代碼,該靜態庫定義了一個全局變量。此全局變量的單個實例在引用其符號的兩個共享庫之間共享。在Linux上,爲什麼析構函數在C++中的全局變量的共享實例上運行兩次?
當進程關閉並且運行靜態終止階段時,我看到此共享實例上的析構函數運行了兩次!據推測,每個圖書館每卸載一次。
這個問題與我最近在這裏看到的另一個密切相關:related question。這聽起來像是一樣的行爲,但沒有討論它爲什麼會發生。
有沒有人知道這種行爲背後的理論解釋?
在Linux上,我從靜態庫中生成了一些C++代碼,該靜態庫定義了一個全局變量。此全局變量的單個實例在引用其符號的兩個共享庫之間共享。在Linux上,爲什麼析構函數在C++中的全局變量的共享實例上運行兩次?
當進程關閉並且運行靜態終止階段時,我看到此共享實例上的析構函數運行了兩次!據推測,每個圖書館每卸載一次。
這個問題與我最近在這裏看到的另一個密切相關:related question。這聽起來像是一樣的行爲,但沒有討論它爲什麼會發生。
有沒有人知道這種行爲背後的理論解釋?
如果你拿一個裸指針並把它放在一個智能指針(兩次)中,它將會破壞兩次,每次一個容器的引用次數降到零。
因此,如果您將裸指針傳遞到兩個庫中,那就可以了。每個人都把它放在一個共享指針對象中,並且每個都會銷燬。如果你可以在dtor期間看到堆棧回溯,那應該在兩個庫中顯示它。
使用任何常規調試器,應該很容易檢查調用堆棧回溯並找出誰在調用此析構函數。 – Vargas 2010-08-05 14:46:05
C++有一個規則被稱爲「一個定義規則」:
每個程序都應該包含在該程序中使用的每個非內聯函數或對象的只有一個定義;不需要診斷。定義可以在程序中顯式出現,它可以在標準庫或用戶定義的庫中找到,或者(在適當的時候)隱式定義(見12.1,12.4和12.8)。
維基百科有一個article,更詳細地解釋了這一點。
您還沒有在您的問題中發佈代碼,所以我無法確定您的情況,但在the question you linked to中,問題的示例是在兩個共享庫中定義相同的變量。這違反了「一個定義規則」,這顯然是動態鏈接器的最終化策略所依賴的,導致析構函數被調用兩次。
它應該只能由編譯器生成的代碼對每個變量運行一次。嘗試在運行析構函數時獲取變量的地址,以驗證它是否是同一個對象。 – 2010-08-04 19:26:35
也許你在一些智能指針類中存儲了一個指向該對象的指針,該指針試圖摧毀它的指針。 – 2010-08-04 19:28:11
因此,全局僅在其中一個庫(的編譯單元)中定義? – Thomas 2010-08-04 19:30:38