Как получить информацию об исключении переполнения буфера в смешанном приложении? - PullRequest
5 голосов
/ 10 января 2012

Во всех разрабатываемых мною приложениях WPF есть глобальный обработчик исключений, подписанный на AppDomain.CurrentDomain.UnhandledException, который регистрирует все, что может найти, а затем отображает диалоговое окно, в котором пользователю предлагается связаться с автором, где находится файл журнала и т. Д. Это работает чрезвычайно Ну, и я, и клиенты очень довольны, потому что это позволяет быстро решать проблемы.

Однако при разработке смешанного приложения WPF / C # / CLI / C ++ иногда возникают сбои приложения, которые не попадают в вышеупомянутый обработчик исключений. Вместо этого появляется стандартное диалоговое окно с надписью «ХХХ перестал работать». В деталях это показывает, например,

 Problem Event Name: BEX
 Application Name:   XXX.exe
 Fault Module Name:  clr.dll
 ...

Это в основном происходит при обратном вызове управляемой функции из неуправляемого кода и когда эта функция обновляет экран. Мне не потребовалось много времени, чтобы выяснить первопричину проблемы, но только потому, что я могу воспроизвести сбой на моей машине и подключить отладчик: во всех случаях нативный поток все еще находился в точке вызова указателя функции на управляемый делегат, вызывающий напрямую в код C # / WPF.

Настоящая проблема может возникнуть, когда это происходит на клиентском компьютере: учитывая, что обычно клиенты не являются лучшими репортёрами ошибок, может потребоваться очень и очень много времени, чтобы выяснить, что не так, когда все, что они могут предоставить мне, это детали выше.

Вопрос: что я могу сделать, чтобы получить больше информации о сбоях, подобных этим? Есть ли способ получить исключение, подобное этому вызову пользовательского обработчика ошибок в любом случае? Или получить дамп процесса? При загрузке символов для msvcr100_clr0004.dll и clr.dll (загруженных в потоке, где происходит разрыв), стек вызовов выглядит следующим образом:

msvcr100_clr0400.dll!__crt_debugger_hook()  
clr.dll!___report_gsfailure()  + 0xeb bytes 
clr.dll!_DoJITFailFast@0()  + 0x8 bytes 
clr.dll!CrawlFrame::CheckGSCookies()  + 0x2c3b72 bytes  

Могу ли я каким-то образом подключить некоторый нативный код C ++ к __crt_debugger_hook () (например, для написания минидампа)? Что приводит меня к дополнительному вопросу: как CheckGSCookies ведет себя на машине без установленного отладчика, будет ли он вызывать тот же код?

обновление некоторые пояснения к коду: нативный C ++ вызывает делегат CLI (для которого указатель нативной функции получается с помощью GetFunctionPointerForDelegate, который, в свою очередь, вызывает C # System.Action. Это действие обновляет строку (привязанный к метке WPF) и вызывает событие, измененное свойством, которое вызывает переполнение буфера (при очень быстром обновлении) в безымянном потоке, который не был создан непосредственно в моем коде.

обновление изучая SetUnhandledExceptionFilter, который сначала ничего не делал, я нашел эту изящную статью , объясняющую, как перехватить любое исключение. Это работает, и я смог записать мини-дамп в фильтр исключений, установленный с помощью этой процедуры. Дамп дает в основном ту же информацию, что и перехватчик отладчика: реальная проблема заключается в том, что строка состояния перезаписывается (вызывается из собственного потока) и одновременно читается из потока пользовательского интерфейса. Все это хорошо, но для этого требуется перехват DLL, что не является моим любимым методом решения проблем. Другой способ все еще был бы хорош.

1 Ответ

3 голосов
/ 10 января 2012

. CLR-версия .NET 4 имеет защиту от атак переполнения буфера. Основная схема заключается в том, что код записывает «cookie» в конец массива или фрейма стека, а затем проверяет, имеет ли этот cookie исходное значение. Если оно изменилось, среда выполнения предполагает, что вредоносная программа скомпрометировала состояние программы и немедленно прервала ее. Этот вид прерывания не проходит через обычный механизм необработанных исключений, который был бы слишком эксплуатируемым.

Вероятность того, что ваша программа действительно подвергается атаке, конечно, невелика. Гораздо более вероятно, что ваш нативный код содержит ошибку указателя и записывает ненужную информацию в структуру CLR или кадр стека. Отладка, которая не легка, повреждение обычно наносится задолго до сбоя. Один из подходов - закомментировать код, пока сбой не исчезнет.

...