intermixing c++ exception handling and SEH (windows)

点点圈 提交于 2020-01-01 03:36:11

问题


I have a function in which I call getaddrinfo() to get an sockaddr* which targets memory is allocated by the system. As many may know, you need to call freeaddrinfo() to free the memory allocated by getaddrinfo().

Now, in my function, there are a few places, where I may throw an exception, because some function failed. My first solution was to incorporate the freeaddrinfo() into every if-block. But that did look ugly for me, because I would have had to call it anyways before my function returns, so I came up with SEH`s try-finally...

But the problem I encountered is, that it is not allowed to code the throw-statements into the __try-block

Then, I read on the msdn and tried to swap the throw-statements into the helper function called from within the __try-block... and voila, the compiler didn´t moan it anymore...

Why is that? And is this safe? This does not make sense to me :/

Code:

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);
}

EDIT:

tried the following and it works with throwing an integer, but does not when i use a class as an 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;
}

Why? :/


回答1:


You could wrap the addrinfo in a class that calls getaddrinfo in the constructor and freeaddrinfo in its destructor.

That way it will always be freed, whether there is an exception thrown or not.




回答2:


You can't mix the two exception types. Under the covers, C++ exceptions use SEH and your SEH exception handler could mess up the exception propogation logic. As a result, the C++ compiler won't allow you to mix them.

PS: Structured Exception Handling is almost always a VERY bad idea. Internally Microsoft has banned the use of SEH except in very limited circumstances. Any component that does use structured exception handling is automatically subject to intense code reviews (we have tools that scan code looking for its use to ensure that no cases are missed).

The problem with SEH is that it's extremely easy to accidentally introduce security vulnerabilities when using SEH.




回答3:


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

That doesn't catch an X, it catches an int&. Since there is no matching catch block, the exception is uncaught, stack unwinding doesn't occur, and __finally handlers don't run.

You can put catch (...) in your thread entrypoint (which is main() for the primary thread) in order to make sure that stack unwinding occurs, although some exceptions are unrecoverable, that's never true of a C++ exception.



来源:https://stackoverflow.com/questions/6708937/intermixing-c-exception-handling-and-seh-windows

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!