簡體   English   中英

在Linux / GCC下將NULL指針訪問轉換為C ++異常

[英]Convert NULL pointer access to C++ exception under Linux/GCC

有沒有辦法將NULL指針訪問轉換為Linux下的C ++異常? 類似於Java中的NullPointerException。 我希望以下程序能夠成功返回,而不是崩潰(假設編譯器在編譯期間無法找出此NULL指針訪問):

class NullPointerException {};

void accessNullPointer(char* ptr) {
    *ptr = 0;
}

int main() {
    try {
        accessNullPointer(0);
    } catch (NullPointerException&) {
        return 1;
    }
    return 0;
}

我不期望任何標准的方法,因為C ++下的NULL指針訪問是未定義的 - 行為,只是想知道如何在x86_64 Linux / GCC下完成它。

我做了一些非常原始的研究,有可能:

  1. 當在Linux下訪問NULL指針時,將生成SIGSEGV。
  2. 在SIGSEGV處理程序內部,程序的內存和寄存器信息將可用(如果sigaction()用於注冊信號處理程序)。 如果程序被反匯編,也可以使用導致SIGSEGV的指令。
  3. 修改程序的內存和/或注冊,並創建/偽造異常實例(可能通過調用低級展開庫函數,如_Unwind_RaiseException等)
  4. 最后從信號處理程序返回,希望程序啟動一個C ++堆棧展開過程就像拋出正常異常一樣。

以下是GCC手冊頁的引用(-fnon-call-exceptions):

生成允許捕獲指令以拋出異常的代碼。 請注意,這需要在任何地方都不存在的特定於平台的運行時支持。 此外,它只允許捕獲指令拋出異常,即內存引用或浮點指令。 它不允許從諸如“SIGALRM”之類的任意信號處理程序拋出異常。

看來這個“特定於平台的運行時”正是我想要的。 任何人都知道這樣的Linux / x86_64運行時? 或者如果沒有這樣的運行時已經存在,請給我一些關於如何實現這樣的運行時的信息?

我希望該解決方案也適用於多線程程序。

不,沒有好辦法,而且不應該這樣做。 源代碼中的throw語句拋出異常。 這對於推理異常安全非常重要:您可以查看代碼並查看可以拋出異常的位置,或許更重要的是,您可以查看代碼並查看不會拋出異常的位置。 如果您做的任何事情都可以拋出異常,那么編寫異常安全的代碼變得非常困難,而不會使用catch子句使其混亂。 微軟在早期的C ++編譯器中嘗試了這一點:他們在操作系統的結構化異常之上捎帶了C ++異常處理,結果是一場災難。

使用signalaltstack()注冊備用信號堆棧。

的第三參數與SA_SIGINFO注冊的信號處理程序的處理程序是一個指向ucontext_t包含所保存的寄存器。 信號處理程序應調整此值以模擬對函數的調用。 然后該函數可以拋出異常。

潛在的復雜性包括需要保留被調用者保存的寄存器的值,x86-64上的紅區(可以禁用)和某些ISA上的返回地址寄存器,例如ARM。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM