Прерывание выполнения функции C и возврат к вызывающей стороне C ++ - PullRequest
0 голосов
/ 09 ноября 2010

В настоящее время у меня проблема с реализацией следующего сценария с использованием следующей конфигурации: 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.

Да, я отладил свое приложение и вижу, что стек вызовов действителен.

Ответы [ 3 ]

1 голос
/ 09 ноября 2010

К сожалению, у меня нет ответа на проблему, как указано - вы пытались запустить ваше приложение под отладчиком, чтобы увидеть, где именно оно заканчивается?

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

0 голосов
/ 10 ноября 2010

Хорошо, ребята,

Я сделал это с помощью sigsetjmp / siglongjmp.Работает как шарм.Я могу перепрыгнуть через функцию в стек функции вызова и выполнить там обработку ошибок.

Спасибо за все предложения.

С наилучшими пожеланиями,

Ованес

0 голосов
/ 10 ноября 2010

Это может быть глупый вопрос, но нужно проверить основной файл? Или запустить ваше приложение в отладчике?

...