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

Inc*_*bus 5 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);
}
Run Code Online (Sandbox Code Playgroud)

编辑:

尝试了下面的内容,它可以抛出一个整数,但是当我使用一个类作为例外时却不行:

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;
}
Run Code Online (Sandbox Code Playgroud)

为什么?:/

Rei*_*man 9

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

PS:结构化异常处理几乎总是一个非常糟糕的主意.除非在非常有限的情况下,微软内部禁止使用SEH.任何使用结构化异常处理的组件都会自动进行密集的代码审查(我们有一些工具可以扫描代码以查找其用途,以确保不会遗漏任何案例).

SEH的问题在于,在使用SEH时,很容易意外地引入安全漏洞.

  • 我非常尊重你,并且你在博客上总是有很好的解释,但我不得不在这里提出异议.当使用`/ EHa`时,Visual C++会混合使用这两种类型.`catch(...)`捕获SEH,并且`__finally`为C++异常执行.我想知道,SEH处理程序是否被禁止,或者只是使用SEH进行流量控制的代码(即它合成了SEH异常)?.NET代码处理各地的SEH异常****. (2认同)
  • 启用/ EHa具有潜在的安全后果.它还禁用了大多数编译器优化,因为编译器必须禁用所有代码流分析(当设置/ EHa时,它告诉编译器*any*指令可能导致异常,而不仅仅是方法调用).一些合法的SEH处理程序是:内核参数探测(其中SEH处理程序是必需的),C++异常处理,.Net异常处理,RPC的异常处理程序和一小部分其他处理程序.所有这些案例都经过深入审查. (2认同)

Bo *_*son 3

您可以将 addrinfo 包装在一个类中,该类调用getaddrinfo构造函数及其freeaddrinfo析构函数。

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