[英]Check if jump buffer is valid or not (non-local jumps)
我們在代碼庫中實現了“longjmp-Restore堆棧環境”。 longjmp
例程由特定的error_exit
函數調用,該函數可以從任何地方調用。
因此,當調用longjmp
時,可能沒有調用setjmp
例程,並且緩沖區可能具有導致崩潰的無效值。
我可以將緩沖區初始化為NULL
還是可以檢查是否有未設置或無效的值。 一種方法是每當調用setjmp
時我都可以設置一個標志變量,我可以檢查它。 但那只是一個黑客。
void error_exit()
{
extern jmp_buf buf;
longjmp(buf, 1);
return 1;
}
我可以這樣做嗎?
void error_exit()
{
extern jmp_buf buf;
if(buf)
longjmp(buf, 1);
return 1;
}
代碼是混合的C / C ++,我知道我可以在任何地方用C ++異常處理替換setjmp
和longjmp
,但現在這是不可能的,我可以用無效緩沖區捕獲longjmp
導致崩潰嗎?
jmp_buf
沒有特別好記錄。 在linux標題中,你可以找到類似的東西:
typedef int __jmp_buf[6];
struct __jmp_buf_tag {
__jmp_buf __jmpbuf; /* Calling environment. */
int __mask_was_saved; /* Saved the signal mask? */
__sigset_t __saved_mask; /* Saved signal mask. */
};
typedef struct __jmp_buf_tag jmp_buf[1];
將其設置為零然后測試整個大小可能會浪費時間。
就個人而言,我會保留一個指向此緩沖區的指針,將其初始化為NULL並在setjmp之前設置它。
jmp_buf physical_buf;
jmp_buf *buf = NULL;
...
buf = &physical_buf;
if (setjmp(*buf)) {
...
}
這與擁有單獨的旗幟的想法相同。 此外,您可以根據需要動態分配jmp緩沖區。
知道緩沖區是否已設置並不是一個真正的問題,您可以只擁有一個包含該信息的輔助變量。
真正的問題是你不能longjmp
橫行,這是有不確定的行為,並且由於根本原因無法工作。 從您調用setjmp
的函數返回后,該函數的堆棧將被無效並被后續調用覆蓋。 所以setjmp
上下文不再有效。 我不是在談論jmp_buf
本身,而是談論它中記錄的堆棧狀態。
所以你唯一能做的就是有一個輔助變量來記錄你是否已經設置了緩沖區,並且一旦你將函數與setjmp
放在一起就會解除設置。
好問題。
據我所知,從POSIX標准( http://pubs.opengroup.org/onlinepubs/9699919799/functions/longjmp.html http://pubs.opengroup.org/onlinepubs/9699919799/functions/setjmp.html http ://pubs.opengroup.org/onlinepubs/9699919799/basedefs/setjmp.h.html ) jmp_buf
是不透明的,除了后一個引用要求它是一個數組類型:
<setjmp.h>
頭文件應定義數組類型jmp_buf
和...sigjmp_buf
。
我相信在實踐中你會保存bzero()
緩沖區,並在跳轉到它之前將它與零進行比較,但理論上,在一些尚待發現的POSIX系統中,所有零jmp_buf
都是允許的。 如果你(我不會)打擾這一點,一個選擇是set_jmp
虛擬緩沖區你永遠不會使用一些跳躍點,然后memcmp
你jmp_buf
反對這種假jmp_buf
做前跳。 這樣你只能使用合法的(即由set_jmp
初始化) jmp_buf
。
另一種方法是維護一個單獨的標志,指示它是否已經初始化(或者在struct
包裝)。
我相信我應該在manpage re set_jmp
和long_jmp
上插入強制警告,因為它使應用程序難以閱讀,並且對信號處理有不可預測的影響(后者用sigsetjmp()
)。 此外,在C ++上下文中,它顯然不會展開您的異常處理程序。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.