gpt4 book ai didi

c++ - 结构化异常情况下的堆栈展开

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:06:00 25 4
gpt4 key购买 nike

这个问题更清楚地描述了 here 所描述的问题.我做了更多调查,发现堆栈展开并没有发生在以下代码段中:

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 编译器编译了这段代码,输出是“Wrapper constructor::AddRef!!!” (即未调用在堆栈上构造的包装器对象的析构函数。这是预期的行为吗?还是 VC 编译器的错误?我可以使用一些编译器标志以便在这种情况下发生堆栈展开吗?

最佳答案

C++ 标准没有提供任何可用于处理未定义行为的方法。即使MS这样做。这是特定于平台的事情——所以要小心。一些这样的浮点异常被转换为 Win32 异常,您可以尝试使用 _set_se_translator() 捕获它们。问题是您可以捕获 Win32 异常,但您的堆栈将无法正确展开。至少那不是你可以赌上性命的东西。这就是练习的徒劳之处。

Update: The exception is thrown intentionally to check the stack unwinding. The question is why Wrapper class's destructor is not getting called. – Naveen

如果是这种情况——请不要这样做。有比通过未定义行为更好的方法来抛出异常。

例如:

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 对象的指针。它应该包含 One 对象的地址。您已将其初始化为 0——地址 0 处没有对象。0 不是任何对象的有效地址(这是由标准保证的)。

关于c++ - 结构化异常情况下的堆栈展开,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/617809/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com