В настоящее время у меня проблема с реализацией следующего сценария с использованием следующей конфигурации: GCC 3.4, Linux.
Я написал инструмент (на C ++), который загружает общую библиотеку (написанную на C). В этой библиотеке есть ошибка, которую я не могу исправить. Проблема в том, что он читает некоторые входные данные и записывает декодированные выходные данные. Иногда, если ввод неправильный, эта библиотека без каких-либо проверок запускает декодирование следующих областей памяти. Это вызывает segfault.
Первоначально моя идея заключалась в том, чтобы поместить ввод в выгружаемую память (linux mmap-syscall) и защитить (mprotect) последнюю страницу от доступа. Устанавливая собственный обработчик SIGSEGV, моё приложение C ++ - может выдавать исключение (при компиляции с флагом GCC -fnon-call-exceptions). Это исключение прервет чтение C lib. Я знаю, что эта библиотека не выделяет никакой памяти (или других ресурсов), которая может быть потеряна при разматывании стека. Весь сценарий работал хорошо в моих модульных тестах, где все было одним приложением C ++. Но теперь, когда C-код из библиотеки вызывается, мое приложение просто завершается ... Нужно ли перестраивать этот C-SO с флагом -fnon-call-exceptions? Я не могу скомпилировать эту библиотеку, но только перекомпоновать ее, так как у меня есть доступ только к файлам obj.
Вот изображение среды исполнения:
+------------C++ APP----------+
| |
| Install SIGSEGV handler |
| code calling C SO functions |
| |
| +----------C SO Functions------------+
| | execute producing SIGSEGV |
| +------------------------------------+
| |
| SIGSEGV Handler called |
| => throw Exception |
| to stop execution of |
| C function |
+-----------------------------+
Другие предложения приветствуются.
Большое спасибо,
Ованес
P.S. Я вижу некоторые предложения и критиков, но все они не оптин. И вот почему: у меня только один интерфейс, где я могу ссылаться на библиотеку. Библиотека используется для декодирования структур данных. Проблема в том, что если у меня есть массив с длиной -1, библиотека начинает декодировать массив с длиной 0xffffff (в 32-битной системе). Ожидание, пока lib не завершится в отдельном процессе, на мой взгляд, не вариант. Прежде всего, декодирование займёт значительное количество времени с одной стороны и приведет к большому количеству мусора с другой. Так как мой инструмент должен надежно показывать декодированный вывод пользователям. И им все еще нужно уметь понять следы.
Я не вижу смысла здесь работать над SIGSEGV. Прежде всего, библиотека читает данные и записывает их в дескриптор файла, который я передал ранее. Я могу настроить, как писать в этот дескриптор (буферизованный или нет). Более того, я точно знаю, что он не выделяет кучу данных или ресурсов. И, наконец, он пытается получить доступ к памяти, которую защищало мое приложение, чтобы избежать таких ошибок. С точки зрения пользователя, я не могу сказать кому-либо: извините, двоичная трассировка была только наполовину декодируемой, потому что некоторые данные были противоречивы. Я знаю, что эти данные были несоответствующими, и я точно знаю, как бороться с этим несоответствием. Так что я могу изящно поправиться. Я думаю, что я попытаюсь использовать функции POSIX sigsetjmp / siglongjmp и надеюсь, что они будут работать лучше в качестве исключения. Действительно, для реализации исключений используются либо setjmp / longjmp, либо sigsetjmp / siglongjmp.
Да, я отладил свое приложение и вижу, что стек вызовов действителен.