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

时间:2011-07-15 14:52:54

标签: c++ exception-handling seh structured-exception

我有一个函数,我在其中调用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;
}

为什么呢? :/

3 个答案:

答案 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 ++来说永远不会这样。异常。