#c_sharp #net
Есть сторонняя библиотека на плюсах которая забирает лог с устройства(сканера отпечатка пальцев) и отдает управляемому коду. Библиотека переодически спрашивает у устройства какие пользователи на него загружены и каких нет грузит туда пользователя с отпечатками. Период в 1 час. Параметры передаются правильные. Проблема в возникновении ошибки в непредсказуемый момент времени когда крашится C++ библиотека. Конкретнее когда пытается забрать список загруженных на устройство пользователей, даже когда список пользователей и отпечатков не менялся. Пробовал добавлять аттрибуты HandleCorruptState и ловить AccessViolation, Win32Exception, ExternalException, Exception, по отдельности и все вместе взятое и ничего, процесс просто падает. Версия .NET 4.6.1. P.S. Ловил AccessViolation в первую очередь, так как при неправильных параметрах передаваемых в плюсовую либу она кидала именно это исключение. Вывод в лог при UnhandledException тоже есть и в логах пусто. ВОПРОС: Как решить эту проблему? Либо поймать исключение, либо как-то изолировать рабочую область чтобы ее можно было бы перезагрузить. Код: https://pastebin.com/MZB9VwY9
Ответы
Ответ 1
Такой вылет может происходить при повреждении управляемой кучи. Куча может повредиться если вы передаете библиотеке управляемый массив, а она что-то записывает за его границами. Или запоминает адрес и обращается к нему когда там уже ничего не лежит. Если вы подозреваете подобную ситуацию - попробуйте добавить методу, который ловит исключения, атрибут [HandleProcessCorruptedStateExceptions] - это поможет отловить такую ситуацию. Но это лишь средство диагностики, программа с поврежденной кучей неработоспособна. Если дело и правда в повреждении кучи, то сделать можно вот что. Во-первых, надо проверить (прочитав в документации) как долго библиотека собирается держать у себя переданные ей массивы. Если дольше чем один вызов метода - то надо выделять ей копию массива при помощи Marshal.AllocHGlobal. То же самое касается любых передаваемых по ссылке структур. Во-вторых, если есть подозрение что все вызовы правильные, а проблема - в выходе за границу, то нужно выделять память через VirtualAlloc, оставив с обоих сторон по зарезервированной странице. Это поможет превратить выход за границы массива в немедленный AccessViolationException, который можно обработать. Но краш C++ библиотеки не обязательно сопровождается исключением. Вот еще возможные способы: std::quick_exit, std::exit, std::abort, std::terminate И все - только стандартные способы, а ведь есть еще и WINAPI... Если библиотека использует что-либо из выше перечисленного - ее надо изолировать в отдельный дочерний процесс, и перезапускать его при падениях. Заодно избавитесь от возможных утечек памяти на стороне библиотеки. Общаться с дочерним процессом можно через Remoting, WCF или по велосипедному бинарному протоколу.
Комментариев нет:
Отправить комментарий