2017-07-29 154 views
0

上節目結束這個簡單的代碼崩潰(Qt的5.9.1,5.4.1 GCC):shared_ptr的<QCoreApplication>崩潰

#include <QCoreApplication> 
#include <memory> 

std::shared_ptr<QCoreApplication> manager; 
int main(int argc, char *argv[]) 
{ 
    manager = std::make_shared<QCoreApplication>(argc, argv); 
} 

我知道通常的方法是在堆棧上聲明一個QCoreApplication實例並在main()結束時銷燬它,但我的用例如下所示:我正在用Boost.Python封裝一個使用Qt的庫,並且在python模塊加載時我像上面那樣初始化Qt。但是,除非強制用戶撥打finalize()方法,否則我無法銷燬QCoreApplication

想法是當庫(python模塊)被卸載時被破壞,但這似乎不起作用。上述預期,如果是這樣,爲什麼? 「破壞秩序問題」是我的第一個猜測,但在這種情況下,這應該被視爲一個錯誤?

+0

應用程序對象是一個全局變量/單例(你可以使用'qApp'或'QCoreApplication :: instance()'來獲得它,初始化可能會做很多事情,我不確定你是否真的卸載它。最好從Python創建應用程序實例,然後使用它。 –

回答

2

問題(正如Lukas在他上面的評論中指出的那樣)是共享指針是一個全局對象,這意味着在進程退出時,它的析構函數將不會在main()返回之後被調用,點(我猜測但非常有信心)QCoreApplication對象的析構函數可能訪問的各種數據結構已經被拆除並處理掉了,所以當它嘗試訪問它們時會發生崩潰。 (例如,你傳遞給QCoreApplication構造函數的argv指針可能不再有效時,該QCoreApplication析構函數運行時間)

不過,我也沒有辦法摧毀QCoreApplication除非我強迫 用戶調用一些finalize()方法。

你可以嘗試的一件事是註冊一個回調函數atexit()刪除QCoreApplication對象。希望atexit()回調將在關閉序列中足夠早地調用,這將使您獲得所需的行爲。 (或者如果一切都失敗了,你可以讓QCoreApplication對象泄漏;因爲這個過程即將被銷燬,我認爲這樣做不會特別有害)

+0

非常明確的解釋,謝謝。從您鏈接的頁面:_ [...]可用於建立共享庫卸載時調用的函數。雖然這似乎適用於我的問題的基本示例,但它不對於python綁定的完整案例。我讀[這裏](https://stackoverflow.com/a/13586487/1229582),應該定義調用序列,但我認爲(從C++ 11開始)[this](http://en.cppreference .com/w/cpp/utility/program/atexit)適用:_函數可以與靜態存儲持續時間同時銷燬對象一起調用..._ – matpen

+0

經過更多測試,我找不到比'QCoreApplication'漏洞更好的解決方案。目的。接受答案,因爲它提供了一個非常合理的解釋。 – matpen