Возможно ли для потребителя библиотеки переопределить обработку исключений C ++? - PullRequest
0 голосов
/ 27 мая 2009

У меня есть C ++ DLL с кодом, подобным этому:

LogMessage( "Hello world" );
try {
    throw new int;
} catch( int* e ) {
    LogMessage( "Caught exception" );
    delete e;
}
LogMessage( "Done" );

Эта DLL загружена каким-либо сторонним приложением, и вызывается приведенный выше код. Проблема в том, что вызывается только первый LogMessage - даже если есть обработчик исключений, поток управления передается неизвестному.

Я вижу это и не могу решить, является ли это какой-то неясной ошибкой, которую нужно исследовать, или просто злой силой потребительского приложения.

Возможно ли для потребительского приложения переопределить обработку исключений C ++ в DLL?

РЕДАКТИРОВАТЬ: Проблема решена после обдумывания всех вещей, чтобы проверить, изложенные в ответах. В реальном коде это не просто throw , есть специальная функция для выброса исключений, которая имеет вызов MessageBoxW () Win32 в отладочной версии. И потребительское приложение испытывало проблемы с отображением окна сообщения (это служба NT) и фактически зависало. Так что это не проблема обработки исключений в C ++.

Ответы [ 5 ]

1 голос
/ 27 мая 2009

Код выглядит хорошо. Но вы можете проверить, есть ли необработанное исключение до того, как будет сгенерировано структурированное исключение throw new int;.

LogMessage( "Hello world" );
try {

     //some unhandled exception here 

    throw new int;
} catch( int* e ) {
    LogMessage( "Caught exception" );
    delete e;
}
LogMessage( "Done" );

Если это так, то вы можете проверить то же самое, используя SetUnhandledExceptionFilter .

Если DLL уже предоставляет фильтр необработанных исключений и если он возвращает EXCEPTION_EXECUTE_HANDLER, то ваш обработчик исключений вызываться не будет.

Вам необходимо использовать _set_se_translator для преобразования исключений win32 в структурированные исключения c ++.

1 голос
/ 27 мая 2009

Код выглядит нормально для меня, но я бы соблазнил добавить еще несколько предложений catch, чтобы посмотреть, не попадает ли он в один из других. А именно, я бы вставил: </p> <pre> catch (const std::exception &ex) { ... log exception ... } catch (...) { ... log exception .. } </pre> <p>

Я ожидаю, что он либо попадет в ловушку указателя (даже если это действительно не очень хорошая идея, см. Ссылку, которую предоставил Игорь Окс), либо в исключение std ::, если он не может выделить память. Тем не менее, он должен попасть в одно из трех предложений catch, чтобы исключение не могло выйти из DLL.

Я бы также изменил брошенный объект на тип значения (даже если это int) и обновил бы предложение catch соответственно, чтобы увидеть, изменилось ли поведение таким образом.

1 голос
/ 27 мая 2009

Сначала проверьте, сбрасывает ли вызов LogMessage выход (используйте << endl).

Хотя это неправдоподобно, возможно ли, что новый вызов выдает исключение (нехватка памяти)? Я бы посчитал это одной из причин не новых исключений (просто чтобы добавить к тому, что сказал Игорь).

1 голос
/ 27 мая 2009

Код в порядке. Я выполнил это с помощью этой функции:

void LogMessage( char* s )
{
  cout << s << endl;
}

И получил правильный вывод:

Привет, мир

Пойманное исключение

Готово

Возможно ли, что есть какая-то проблема с вашей LogMessage функцией?

Я бы предложил выяснить (путем отладчика или добавления отладочных отпечатков), достигает ли ваш поток блока try и достигает ли он блока catch.

Не будучи проблемой, до сих пор не ясно, чего вы добиваетесь, бросая указатель, а не значение. Я бы порекомендовал не использовать перехват указателя, см. Обоснование здесь , на C ++ - FAQ-lite.

0 голосов
/ 28 мая 2009

Дешевая распродажа на самом деле в редактировании. Msgstr "Служба MessageBoxW () ... NT ... фактически зависла." Это честное описание. Окно сообщения на рабочем столе не связано с вошедшим в систему пользователем. Следовательно, он все еще там, ожидая щелчка мышью, который никогда не произойдет.

...