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