簡體   English   中英

在結構化異常的情況下展開堆棧

[英]Stack unwinding in case of structured exceptions

這個問題更清楚地說明了這里描述的問題。 我做了更多調查,發現堆棧展開沒有發生在以下代碼中:

class One
{
public:
    int x ;
};

class Wrapper
{
public:
    Wrapper(CString csText):mcsText(csText)
    {
        CString csTempText;
        csTempText.Format("Wrapper constructor :: %s\n", mcsText);
        OutputDebugString(csTempText);
    }

    ~Wrapper()
    {
        CString csTempText;
        csTempText.Format("Wrapper destructor :: %s\n", mcsText);
        OutputDebugString(csTempText);
    }
    CString mcsText;
};
class Test
{
    public:

    void notifyError()
    {
        try
        {
            int x = 10; 
        }
        catch(...)  {}
    }

    void OnRecvBuffer()
    {
        try
        {
            Wrapper a("AddRef");    
            One* p = NULL;
            p->x = 10;
        }
        catch(...)
        {
            notifyError();
        }   
    }   
};



int main() 
{
    Test* pTest = new Test;

    pTest->OnRecvBuffer();

    OutputDebugString("Test");
}

我使用 VC6 SP5 編譯器編譯了這段代碼,output 是“包裝器構造函數::AddRef ...”(即?沒有調用在堆棧上構造的包裝器 object 的析構函數?這是預期的行為嗎?還是它VC 編譯器的錯誤?我可以使用一些編譯器標志,以便在這種情況下發生堆棧展開嗎?

C++ 標准沒有提供任何可用於未定義行為的情況。 即使 MS 有。 這是特定於平台的事情——所以要小心。 一些這樣的浮點異常被轉換為 Win32 異常,您可以嘗試使用_set_se_translator()來捕獲這些異常。 問題是您可以捕獲 Win32 異常,但是您的堆棧將無法正確展開。 至少這不是你可以賭上生命的事情。 這就是練習的徒勞。

更新:故意拋出異常以檢查堆棧展開。 問題是為什么 Wrapper 類的析構函數沒有被調用。 – 納文

如果是這種情況 - 不要這樣做。 有比通過未定義行為更好的方法來引發異常。

例如:

void OnRecvBuffer()
{
    try
    {
        Wrapper a("AddRef");    
        throw 42; // this'll throw an exception without invoking UB
    }
    catch(...)
    {
        notifyError();
    }
}

您不能取消引用 NULL 指針。 您在這里調用未定義的行為:

One* p = NULL;
p->x = 10;

在那條線之后,所有的賭注都被取消了,你本可以殺了我們所有人;)

p是指向One object 的指針。 它應該包含One object 的地址。 您已將其初始化為 0 - 地址 0 處沒有 object。0 不是任何 object 的有效地址(這是由標准保證的)。

如果要使用 SEH,則必須使用 _set_se_translator function 和 /EHa 編譯器選項。

因為 C++ 常規異常不處理此類異常,所以您必須使用對應用程序一無所知且不會展開的 SEH。

這是未定義的行為:

One* p = NULL;
p->x = 10;

此時,應用程序可以在不展開堆棧的情況下自由崩潰。
如果要測試堆棧展開,請將其替換為:

 throw 42; // Life the Universe and Everything thrown away

您不應該動態分配所有對象,這是 C++ 而不是 Java!

int main() 
{
    Test    pTest;   // Note the lack of new!

    pTest.OnRecvBuffer();

    OutputDebugString("Test");
}

暫無
暫無

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

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