2011-08-31 44 views
5

我想在C程序中使用setjmp和longjmp,該程序鏈接到使用C++實現的庫(但具有C API)。使用C語言中的setjmp和longjmp鏈接到C++庫時

C++代碼確實做動態內存分配,並且指針通過API傳遞,但只要代碼的C端正確管理那些(不透明)對象,在使用longjmp時不應該有任何混亂,對?

我知道在C++代碼中使用這些函數並不安全,但是應該在C代碼中安全嗎?

回答

3

從C代碼中調用C++函數並不會使setjmp和longjmp比以往更加不安全。

重要的是,如果你的庫分配資源,你必須有適當的恢復代碼以確保在調用longjmp之後這些代碼被正確釋放。雖然這對您自己的分配很容易,但根據您使用的C接口的結構,C++庫可能很難或不可能。

+0

好的。我的想法是,只要通過適當的C接口調用清理C++庫中的分配,C++代碼就可以與longjmp的效果隔離開來,異常處理和longjmp不會干擾每個其他。 (我也是C++庫的實現者)。 –

+0

如果你在C++庫中有異常處理,你應該確保任何拋出的異常在庫中被捕獲,你不希望異常使它超出你的C++代碼(不知道如果你這樣做會發生什麼,從來沒有嘗試過)。並且爲了釋放C++分配,你必須弄清楚在longjmp調用之後需要控制的C代碼需要釋放什麼。既然你擁有應用程序和庫,我沒有看到任何問題來完成這項工作。 – Miguel

2

setjmp/longjmp通常是而不是可以安全地用於C++。它們有效地複製異常的行爲,但不正確地展開堆棧(例如,它們不會爲在堆棧框架上強制退出的對象運行析構器)。如果可能的話,如果你有它們,則使用異常。

+0

OP並沒有試圖在C++中使用'setjmp' /'longjmp',而是通過C接口使用一些C++代碼的C程序(它可能將所有C++代碼掩碼爲C調用的代碼,並且這樣做安全)。 –

+2

即使如此,它依賴於。在自己的代碼中跳轉可能是安全的,但使用'longjmp'退出回調(例如)可能會造成嚴重破壞。 – duskwuff

+0

使用'longjmp'來退出回調(除非明確給出了這樣的權限),不管語言如何,聽起來都是一個壞主意。你也必須在C後清理自己。 –

1

好吧,對,不對。 longjmp一般不會調用析構函數,所以使用它像下面這樣的代碼:

void f(jmp_buf jb) 
{ 
    some_cpp_object_with_a_nontrivial_destructor x; 
    if (some_condition) longjmp(jb, 2); 
    // some other code 
} 

會做出種種不好的事情發生。如果你避免這種情況,你應該沒問題。 (一般來說,longjmp不得跳過任何活動堆棧幀與對象具有非平凡的析構函數。)

+0

我的代碼是C,所以我不能用具有構造函數的類型定義局部變量。因此你的例子不適用於我的問題。 –

+0

如果您給C++函數一個回調,並且回調函數調用longjmp,那麼最終會出現類似的情況。 – zvrba