混合c++异常处理和SEH (windows)

intermixing c++ exception handling and SEH (windows)

本文关键字:windows SEH c++ 异常处理 混合      更新时间:2023-10-16

我有一个函数,我调用getaddrinfo()来获得一个sockaddr*,它的目标内存是由系统分配的。许多人可能知道,您需要调用freeaddrinfo()来释放getaddrinfo()分配的内存。

现在,在我的函数中,有几个地方,我可能会抛出异常,因为某些函数失败了。我的第一个解决方案是将freeaddrinfo()合并到每个if块中。但这对我来说确实很难看,因为我必须在函数返回之前调用它,所以我想出了SEH的try-finally…

但是我遇到的问题是,不允许将throw语句编码到__try-block

然后,我在msdn上阅读并尝试将throw语句交换到__try块内调用的helper函数中…瞧,编译器再也不会抱怨了…

为什么?这安全吗?这对我来说没有意义:/

代码:

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 __tryn";
            Helper();
            std::cout << "leaving __tryn";
        }
        __finally
        {
            std::cout << "in __finallyn";
        }
};

int _tmain(int argc, _TCHAR* argv[])
{
    try
    {
        base();
    }
    catch(int& X)
    {
        std::cout << "caught a X" << std::endl;
    }
    std::cin.get();
    return 0;
}

为什么?:/

不能混合使用这两种异常类型。在幕后,c++异常使用SEH,而您的SEH异常处理程序可能会弄乱异常传播逻辑。因此,c++编译器不允许你混合使用它们。

PS:结构化异常处理几乎总是一个非常糟糕的主意。微软内部禁止使用SEH,除非在非常有限的情况下。任何使用结构化异常处理的组件都会自动接受严格的代码审查(我们有工具扫描代码查找其使用,以确保没有遗漏任何情况)。

SEH的问题是在使用SEH时非常容易意外地引入安全漏洞。

可以将addrinfo封装在一个类中,该类在构造函数中调用getaddrinfo,在析构函数中调用freeaddrinfo

这样,无论是否抛出异常,它都将被释放。

catch(int& X)
{
    std::cout << "caught a X" << std::endl;
}

没有捕获X,它捕获了int&。由于没有匹配的catch块,异常被捕获,堆栈不展开,__finally处理程序不运行。

您可以将catch (...)放在线程入口点(对于主线程来说是main()),以确保堆栈展开发生,尽管有些异常是不可恢复的,但对于c++异常来说,这永远不会发生。