Распространение исключений C ++ по всем фреймам стека C в OS X - PullRequest
1 голос
/ 05 января 2009

Приложение, над которым я работаю (на самом деле это игра), использует XML для некоторых своих настроек. Так как я использую CEGUI для GUI, и у него есть свои собственные объекты синтаксического анализа XML, я преобразовал свой код, чтобы использовать его вместо моего собственного класса анализатора, созданного вручную. Если в документе отсутствуют атрибуты по определенным тегам, он выдает исключение, чего я и хочу. Однако исключение не распространяется через вызовы C в стеке; вместо этого вызывается terminate ().

Для тех из вас, кто не знаком с CEGUI, он использует систему на основе плагинов для анализа XML. В настоящее время есть плагины для tinyxml, expat, libxml и xerces. Ни один конкретный плагин не гарантированно присутствует в конкретном двоичном дистрибутиве CEGUI; единственное требование - наличие хотя бы одного. Поэтому моя проблема не может быть решена с помощью использования синтаксического анализатора C ++ (tinyxml или xerces).

Кто-нибудь знает хороший способ обойти эту проблему, который не требует от меня распространения исходного кода для CEGUI и его зависимостей плагина XML-парсера с моим исходным кодом игры?

Я также должен отметить, что эта проблема возникает только в OS X; он отлично работает на GNU / Linux.

Вот простой пример кода, который демонстрирует проблему:

EDIT: небольшая коррекция кода http://pastebin.com/m23ba5577

Спасибо, Роб

Ответы [ 6 ]

4 голосов
/ 07 января 2009

В отношении источника, который вы опубликовали, если вы скомпилируете test.c с помощью компилятора C ++, все будет работать как положено (вам нужно будет сделать функции extern "C", что, как я понимаю, вы не сможете вне вашего примера).

Разница в генерируемых символах проливает свет на происходящее:

Компилятор C ++: g++ -c test.c

00000040 s EH_frame1
         U ___gxx_personality_v0
0000001a T _callIt
0000005c S _callIt.eh
00000088 b _callback
00000000 T _setCallback
00000000 A _setCallback.eh

C компилятор: gcc -c test.c

00000019 T _callIt
0000003c b _callback
00000000 T _setCallback

Как видите, для каждой функции есть дополнительный символ, заканчивающийся на ".eh", и EH_frame1 - они содержат описание фреймов вызова, которые должны быть отменены в случае возникновения исключения. Если они отсутствуют ... ничего не делать, кроме вызова terminate ().

Учитывая, что C не поддерживает исключения, компилятор C не будет записывать эти символы в объектный файл.

Так что, если вы не контролируете, как эти библиотеки компилируются, вам лучше всего установить обработчик SIGABRT перед синтаксическим анализом и рассматривать его вызов как «исключение произошло». Вам все еще не хватает фактической информации об ошибке, но вы будете знать, что она произошла.

0 голосов
/ 06 января 2009

Я определенно не эксперт, но по тому, что я могу определить; поведение среды выполнения C / C ++ в отношении исключений C ++, возникающих при наличии функций C в стеке, определяется реализацией.

Мне любопытно, что вы используете исключения C ++ в качестве механизма для обработки пропущенных атрибутов. Поддерживают ли библиотеки XML C таким образом исключения C ++? Другими словами, правильно ли высвобождаются ресурсы времени выполнения C при наличии исключения, учитывая, что библиотеки предназначены для языка C?

Я бы порекомендовал вам сузить использование библиотек XML до библиотек, поддерживающих C или C ++, а не обе, чтобы вы могли реализовать один механизм ошибок.

0 голосов
/ 05 января 2009

Это правда, я получил ответ на этот вопрос на форумах разработчиков Apple. Однако это не значит, что это единственный ответ. На самом деле я получил четыре ответа, каждый из которых неоптимален:

  • Распространите Expat, libxml и CEGUI с моим приложением и убедитесь, что Expat и libxml используют -fexceptions при сборке на OS X.
  • Ограничьте плагины анализатора, которые мое приложение может использовать в OS X, плагинами tinyxml и xerces.
  • Оберните мой код чтения XML в конструкцию setjmp / longjmp и сгенерируйте исключение, если setjmp вернет истинное значение.
  • Полностью избавьтесь от XML и CEGUI в моем приложении.

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

0 голосов
/ 05 января 2009

У меня такое чувство, что вы ответили на свой вопрос

http://discussions.apple.com/thread.jspa?threadID=1852579&tstart=0

0 голосов
/ 05 января 2009

Извините за это; Я только добавил исправление. Если вы скомпилируете и запустите этот код в OS X, вы заметите, что он все еще завершается ().

Что касается моего комментария, так это то, что это простая демонстрация проблемы без публикации всего кода моего приложения. = D

0 голосов
/ 05 января 2009

В примере кода ничего не ловит исключение. В таком случае (когда выброшенное исключение не имеет соответствующего блока catch), среда выполнения c ++ вызывает std :: terminate.

Но я не понимаю, какое отношение это имеет к телу вашего вопроса ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...