Search code examples
c++exceptionsehstructured-exception

intermixing c++ exception handling and SEH (windows)


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? :/


Solution

  • 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.