我有一个函数,我在其中调用getaddrinfo()
来获得一个sockaddr*
,其中目标内存由系统分配。
许多人可能知道,你需要调用freeaddrinfo()
来释放getaddrinfo()分配的内存。
现在,在我的函数中,有一些地方,我可能会抛出异常,因为某些函数失败了。
我的第一个解决方案是将freeaddrinfo()
合并到每个if块中。
但对我来说这看起来确实很难看,因为在我的函数返回之前我不得不调用它,所以我想出了SEH的尝试 - 终于......
但我遇到的问题是,不允许将throw语句编码到__try-block中
然后,我读了msdn并尝试将throw语句交换到__try-block中调用的辅助函数...瞧,编译器不再呻吟了......
为什么?这样安全吗?这对我没有意义:/
代码:
void function()
{
//...
addrinfo* pFinal;
__try
{
getaddrinfo(..., &pFinal);
//if(DoSomething1() == FAILED)
// throw(exception); //error C2712: Cannot use __try in functions that require object unwinding
//but this works
Helper();
//...
}
__finally
{
freeaddrinfo();
}
}
void Helper()
{
throw(Exception);
}
编辑:
尝试了以下内容,它可以抛出一个整数,但是当我使用一个类作为例外时却不行:
class X
{
public:
X(){};
~X(){};
};
void Helper()
{
throw(X());
}
void base()
{
__try
{
std::cout << "entering __try\n";
Helper();
std::cout << "leaving __try\n";
}
__finally
{
std::cout << "in __finally\n";
}
};
int _tmain(int argc, _TCHAR* argv[])
{
try
{
base();
}
catch(int& X)
{
std::cout << "caught a X" << std::endl;
}
std::cin.get();
return 0;
}
为什么呢? :/
答案 0 :(得分:9)
您不能混合使用这两种异常类型。在幕后,C ++异常使用SEH,您的SEH异常处理程序可能会破坏异常传播逻辑。因此,C ++编译器不允许您混合它们。
PS:结构化异常处理几乎总是一个非常糟糕的主意。除非在非常有限的情况下,微软内部禁止使用SEH。任何使用结构化异常处理的组件都会自动受到强烈的代码审查(我们有扫描代码的工具,以确保不会遗漏任何案例)。
SEH的问题在于使用SEH时很容易意外引入安全漏洞。
答案 1 :(得分:3)
您可以将addrinfo包装在一个在构造函数中调用getaddrinfo
并在其析构函数中调用freeaddrinfo
的类中。
这样,无论是否抛出异常,它都会被释放。
答案 2 :(得分:0)
catch(int& X) { std::cout << "caught a X" << std::endl; }
它没有捕获X
,它捕获int&
。由于没有匹配的catch块,因此未捕获异常,不会发生堆栈展开,并且__finally
处理程序不会运行。
您可以将catch (...)
放在线程入口点(主线程为main()
)中,以确保发生堆栈展开,尽管有些异常是不可恢复的,但对于C ++来说永远不会这样。异常。