Мне потребовался целый день, чтобы выяснить, в чем дело.
Теперь я должен немного глубже объяснить, что я делаю. У меня есть код C ++, который компилируется в файл LIB. Приведенный выше код (Tester и Thrower) находится в этом простом файле LIB C ++.
И у меня есть еще один код C ++, который компилируется в управляемую DLL C ++, которая связана с этим файлом LIB. Итак, в конце оба кода находятся в одной и той же DLL. Я управлял функциями оболочки, которые вызывают код в файле LIB следующим образом:
ManagedWrapper()
{
try
{
Thrower();
}
catch (std::exception& e)
{
throw new System::Exception(e.what());
}
}
Это НЕ работает. С помощью этого кода у меня возникают утечки памяти и сетевые сокеты, которые не закрываются. Стек в Thrower не раскручивается.
Причина этого в том, что разматывание стека не происходит до достижения захвата. Но когда catch находится в другой библиотеке, чем throw, стек не разматывается. DLL не знает, как раскрутить стек в файле LIB (хотя оба, наконец, скомпилированы в одну и ту же DLL !!)
Но я нашел чрезвычайно простое решение.
В файле LIB мне пришлось добавить промежуточную функцию между ManagedWrapper () и Thrower (), как это. Код выглядит глупо, но проблему решает:
Catcher()
{
try
{
Thrower();
}
catch(...) // unwind HERE
{
throw;
}
}
Важно то, что этот уловитель должен находиться в файле LIB, в котором генерируется исключение. Когда исключение перехвачено, стек разматывается, а затем исключение повторно передается управляемой оболочке.
Иногда код, который выглядит глупо, оказывается очень умным!
РЕЗЮМЕ: никогда не забывайте, что исключение всегда должно перехватывать ту же библиотеку, в которой оно было создано. Если они попадают за границу библиотеки, у вас серьезные проблемы.
person
Elmue
schedule
25.01.2014