Смешивание обработки исключений C++ и SEH (windows)
У меня есть функция, в которой я звоню getaddrinfo()
чтобы получить sockaddr*
какая целевая память выделяется системой. Как многие могут знать, вам нужно позвонить freeaddrinfo()
освободить память, выделенную функцией getaddrinfo().
Теперь в моей функции есть несколько мест, где я могу выдать исключение, потому что какая-то функция завершилась ошибкой. Моим первым решением было включить freeaddrinfo()
в каждый блок if. Но это выглядело уродливо для меня, потому что мне пришлось бы в любом случае вызывать его до того, как моя функция вернется, поэтому я пришел к SEH, который попробовал окончательно...
Но проблема, с которой я столкнулся, заключается в том, что не разрешено кодировать операторы throw в блок __try-
Затем я прочитал msdn и попытался поменять операторы throw в вспомогательную функцию, вызываемую из __try-блока... и вуаля, компилятор больше не стонал...
Это почему? И это безопасно? Это не имеет смысла для меня:/
Код:
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;
}
Зачем?:/
3 ответа
Вы можете обернуть addrinfo в класс, который вызывает getaddrinfo
в конструкторе и freeaddrinfo
в своем деструкторе.
Таким образом, он всегда будет освобожден, независимо от того, было ли выброшено исключение или нет.
Вы не можете смешивать два типа исключений. Под прикрытием исключения C++ используют SEH, и ваш обработчик исключений SEH может испортить логику распространения исключений. В результате компилятор C++ не позволит вам смешивать их.
PS: Структурная обработка исключений почти всегда является ОЧЕНЬ плохой идеей. Внутренне Microsoft запретила использование SEH, за исключением очень ограниченных обстоятельств. Любой компонент, который использует структурированную обработку исключений, автоматически подвергается интенсивным проверкам кода (у нас есть инструменты, которые сканируют код в поисках его использования, чтобы убедиться, что ни одно из случаев не пропущено).
Проблема с SEH заключается в том, что при использовании SEH очень легко случайно внедрить уязвимости безопасности.
catch(int& X) { std::cout << "caught a X" << std::endl; }
Это не ловит X
ловит int&
, Так как нет соответствующего блока catch, исключение uncaught, разматывание стека не происходит, и __finally
обработчики не работают
Вы можете положить catch (...)
в вашей теме входа потока (который main()
для основного потока), чтобы гарантировать, что разматывание стека происходит, хотя некоторые исключения не восстанавливаются, это никогда не относится к исключению C++.