При разработке SWIG-библиотеки С++ для Ruby мы столкнулись с необъяснимым сбоем при обработке исключений внутри кода С++.
Я не уверен в конкретных обстоятельствах, чтобы воссоздать проблему, но это произошло во время вызова std::uncaught_exception
, а затем после изменения какого-либо кода, переместился на __cxa_allocate_exception
во время построения исключения. Ни GDB, ни valgrind не дали никакого понимания причины аварии.
Я нашел несколько ссылок на похожие проблемы, в том числе:
- http://wiki.fifengine.de/Segfault_in_cxa_allocate_exception
- http://forums.fifengine.de/index.php?topic=30.0
- http://code.google.com/p/osgswig/issues/detail?id=17
- https://bugs.launchpad.net/ubuntu/+source/libavg/+bug/241808
Приоритетная тема, кажется, представляет собой сочетание обстоятельств:
- Приложение C связано с более чем одной библиотекой С++.
- Во время компиляции была использована более одной версии libstdС++.
- Обычно вторая версия С++ используется из бинарной реализации libGL
- Проблема не возникает при связывании вашей библиотеки с приложением С++, только с приложением C
"Решение" - это явно связать вашу библиотеку с libstdС++ и, возможно, также с libGL, заставляя порядок связывания.
После нескольких комбинаций с моим кодом единственным решением, которое я нашел, что работает, является параметр LD_PRELOAD="libGL.so libstdc++.so.6" ruby scriptname
. То есть ни один из решений компоновки времени не имел никакого значения.
Мое понимание проблемы заключается в том, что среда выполнения С++ не была правильно инициализирована. Заставляя порядок связывания вы запускаете процесс инициализации, и он работает. Проблема возникает только с приложениями C, вызывающими библиотеки С++, потому что приложение C не связано непосредственно с libstdС++ и не инициализирует среду выполнения С++. Поскольку использование SWIG (или boost:: python) является распространенным способом вызова библиотеки С++ из приложения C, вот почему SWIG часто возникает при исследовании проблемы.
Есть ли кто-нибудь, кто мог бы лучше понять эту проблему? Существует ли реальное решение или существуют только обходные пути?
Спасибо.