2017-02-22 106 views
1

它是安全的呼籲刪除一個基類指針通過動態加載庫分配的堆對象?該lib和客戶端都由相同的編譯器(GCC)構建。安全++

+0

(加載的lib通過以通常的方式調用「new」來分配它 - 不使用就地提供給我的內存地址的「new」,或類似的東西)。 –

+1

看起來像這個問題來自用法的MS東西。不,的Linux/Unix系統中實現共享庫正確放在第一位,而不是廢話從MS – Slava

+0

如果我能找到一個官方十歲上下的基準說爲多,這會解決我的問題。 :) –

回答

0

是的,如果它被分配了new,並且庫(或任何其他代碼)在刪除後不嘗試使用該對象。

+1

析構函數必須聲明爲「虛擬」。 – mch

+0

@mch你能詳細說明原因嗎? – emlai

+0

如果基類的析構函數不是虛擬的,當刪除基指針時,它不會調用派生類的析構函數。 – mch

4

它是安全的delete指針當且僅當

  • 基類的析構函數是虛擬的。
  • 指針被new返回(不new[],不malloc,不mmap,...)
  • 您是指針的唯一所有者。換句話說:如果沒有其他代碼片段(在dll內或在dll外)將要使用或銷燬尖銳的對象。

至於標準而言,該庫必須使用相同版本的運行時庫定義配置功能的鏈接。相同的要求適用於靜態鏈接在一起的單獨對象文件。在技​​術上,內存分配函數的多種不同實現違反了一個定義規則,但是用標準庫擴展語言的C++實現可能會擴展語言以允許這些函數的多種不同實現。如果這是您所使用的執行的話,那麼它可能不會是安全的解除分配共享庫分配的內存,除非你能證明同樣的版本中使用的庫以及刪除的對象的代碼兩者。


無論是安全與否,這是一個壞主意,以提供返回的資源(如動態內存),其採用釋放這些資源照顧的API,而不是API。

+0

錯誤,析構函數不一定是虛擬的,以便刪除是安全的。如果你想要調用任何派生類的析構函數,它只是虛擬的。 – emlai

+1

@tuple_cat *「如果要刪除的對象的靜態類型與其動態類型不同,則靜態類型應爲要刪除的對象的動態類型的基類,並且**靜態類型應具有一個虛擬的析構函數或行爲是未定義的**。「*所以說標準。 – user2079303

+0

@tuple錯誤 - 標準說如果基本析構函數不是虛擬的,則通過基指針刪除派生對象是未定義的行爲。該標準沒有說明在這種情況下可能或不可能調用哪些析構函數。 –

1

這取決於編譯器和標誌是動態庫編譯時使用的版本。

圖書館對new的調用會從庫控制的堆中抓取對象。

您對delete的呼叫將對象放回由可執行文件控制的堆。

這可能是也可能不是由同一庫管理的相同的堆。

安全的方法是將delete包裝在庫調用中,如fopen/fclose。

+0

聽到關於這個謠言是什麼促使我的問題,實際上。我很想知道這種雙堆行爲是否僅由隱蔽的操作系統完成,或者是否主流Linux發行版這樣做。 –

+0

我在動態庫被編譯爲舊版本的g ++時看到了它。這是很久以前,現在可能有更好的解決方案。在任何情況下,請考慮使用g ++編譯的可執行文件以及使用英特爾編譯器編譯的庫:) – Arkadiy

+0

在Unix/Linux世界中沒有「庫控制的堆」這樣的事情。正如OP問題所說的gcc,這可能意味着Linux,這不是一個問題。 – Slava