6

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

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

但是我遇到的问题是,不允许将 throw-statements 编码到 __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;
}

为什么?:/

4

3 回答 3

9

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

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

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

于 2011-07-15T15:30:46.850 回答
3

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

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

于 2011-07-15T15:30:22.013 回答
0
catch(int& X)
{
    std::cout << "caught a X" << std::endl;
}

那不抓住一个X,它抓住一个int&。由于没有匹配的 catch 块,异常未被捕获,堆栈展开不会发生,并且__finally处理程序不会运行。

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

于 2011-07-16T01:25:53.483 回答