Переполнение стека в неуправляемой библиотеке приводит к сбою приложения.NET

Потому что мне часто приходится использовать библиотеки сторонних производителей - а иногда они приводят к сбою моих приложений - я создал тестовую библиотеку на C++. Эта библиотека генерирует переполнение стека (путем рекурсивного вызова метода) с намерением. Тестовое приложение, созданное с помощью.NET 4.6, вызывает экспортированный метод... и вылетает.

  • Попробуй поймать? Не будет достигнуто и не имеет никакого эффекта.
  • AppDomain.UnhandledException? Не будет достигнуто и не имеет никакого эффекта.
  • Выполнить метод в собственном домене приложений? Не имеет никакого эффекта

Поймать "нормальное" исключение, вызванное throw, не проблема для моего тестового приложения.

Как я могу поймать такого рода исключения?

1 ответ

С точки зрения C#, вы не поймете исключение. Переполнение стека в нативном коде довольно плохо. Вызывающий поток может иметь половину объекта в стеке, и вы никак не можете его раскрутить.

На самом деле, вы можете приостановить нарушающий поток, что означает, что код C++ не вернется в C#. Это не является непосредственно фатальным - потоки все время приостанавливаются ОС, когда нет доступного ядра ЦП. Но мьютексы останутся заблокированными и т. Д.

Пока нить-нарушитель приостановлена, ваш код C# должен выполнить аварийное сохранение всех вещей, которые могут быть спасены. Затем запланируйте перезапуск (здесь может помочь планировщик заданий Windows) и принудительно завершите весь процесс.

Это оставляет одну "маленькую" деталь: отлов переполнения стека и приостановка этого потока. Это, вероятно, лучше всего сделать с помощью обработчика исключений Vectored, который вызывается непосредственно Windows. В этом обработчике исключений проверьте объект исключения, чтобы убедиться, что это переполнение стека. Если это так, у вас есть проблема, так как вы сейчас работаете в потоке, который доходит до последней страницы стека (и он тоже может быть почти заполнен). Итак, вы делаете только две вещи: звоните ResumeThread(helperThread) а потом SuspendThread(GetCurrentThread()), Вспомогательный поток просыпается, перезванивает в C#, чтобы инициировать аварийное сохранение, а затем вызывает TerminateProcess,

Другие вопросы по тегам