2017-02-06 3 views
11

Допустим, у меня есть разделяемая библиотека, которая реализована на C++, но предоставляет чистый c-интерфейс. Эта библиотека затем используется в c-программе.Поведение исключений C++ escaping в c-программу

Предоставляет ли gcc какие-либо гарантии о том, что происходит, если исключение выходит из библиотеки C++ в приложение c?
Будет ли это, например. всегда заканчивать программу?

Меня больше всего интересует ответ gcc на Linux на x64 и ARMv7-R, но ответы на другие операционные системы, компиляторы и архитектуры также приветствуются.

EDIT:
Просто сделать это ясно: я не говорю о разрешении исключения проходят через с-функции, а затем быть пойманы в вызывающей функции C++ или взаимодействия с С или С ++ обратных вызовов. Сам код приложения является чистым c. В какой-то момент он будет вызывать функцию общей библиотеки (которая внутренне является чистым C++), и код приложения не будет вызываться до тех пор, пока эта функция не вернется. Также предположим, что я не могу контролировать, какие флаги используются для компиляции кода приложения.

+0

I_believe_, что такое исключение будет рассматриваться как неперехваченное исключение (т. Е. Генерирует вызов на 'std :: terminate'), если код C не скомпилирован с' -fexceptions', и в этом случае исключение может распространяться (хотя может все еще быть невостребован). Однако у меня нет поддающегося проверке источника. – davmac

+0

Это одна из причин, почему, если вы смешиваете C и C++, общая директива заключается в том, что 'main()' компилируется как C++, а не как C, а функции 'extern 'C' 'ломают исключения и не позволяют им распространяться вызывающему абоненту. Либо это, либо код C++ скомпилирован без поддержки или вообще не бросается. Распространение исключения C++ с помощью функции C не определено. – Peter

+0

@Peter: Да, я не доволен ситуацией, но это то, что есть. Библиотека используется c-программами - я не могу ее изменить. Если я забыл уловить какое-то исключение при завершении пограничной программы, то - вообще - приемлемо для меня (в частности, я обычно не пытаюсь восстановить из «bad_alloc»), но я не хочу рисковать неопределенным поведением. Таким образом, вопрос, с которым я столкнулся, заключается в том, что я должен включить реализацию всех функций интерфейса в дополнительный 'try {...} catch (...) {std :: terminate(); } ', чтобы быть в безопасности, или я могу полагаться на компилятор для получения того же эффекта. – MikeMB

ответ

1

Из того, что я вижу, об исключениях C++, в this example который я взял from MSDN, GCC, кажется, включает следующую сборку в заявлении загвоздка:

call __cxa_end_catch 
    jmp  .L37 
    movq %rax, %rbx 
    call __cxa_end_catch 
    movq %rbx, %rax 
    movq %rax, %rdi 
    call _Unwind_Resume 

, который использует библиотеку, что я могу только предположить, являются C++ вызовы функций, которые относятся к исключениям (например, _Unwind_resume). Поэтому, если код C ссылается на вашу библиотеку, он должен будет предоставить эти символы/функции, что означает, что код будет вводить библиотеку C++ для устранения исключений.

Однако я еще не знаю, что требует библиотека C++ для выполнения своей работы. Я ожидал бы, что это будет самодостаточным, но я не уверен в этом.

Edit: Ответ на этот вопрос, скорее всего, лежит в ответах на следующие два существующих вопросов (и их интерпретации):

  1. How is the C++ exception handling runtime implemented?
  2. How are exceptions implemented under the hood?
  3. How do exceptions work (behind the scenes) in c++

Редактировать 2: От this answer, кажется, что с __cxa_throw используется таблица для отслеживания доступных обработчиков. Я бы предположил, что когда таблица исчерпана, , которая в нашем случае возникает, когда мы вводим код C, функция вызовет std::terminate. Следовательно, среда выполнения C++ (на которую вы должны были установить связь) должна позаботиться об этом для вас, если вам не нужно выставлять предложение catch all.

Поскольку я все еще не уверен, я напишу тест этой теории и обновить ответ с результатами.

+0

Любые обновления по этому вопросу? Я склонен принять ваш ответ, но будет чувствовать себя лучше, если он будет поддерживаться - если не официальной документацией - некоторые тесты. – MikeMB

1

Если исключение C++ выходит из внешнего блока try (который может быть только в самом внешнем вызове функции C++), то исключение не может быть обнаружено.

Неперехваченное исключение всегда приводит к прекращению на std::terminate, в соответствии со стандартом C++, §15.3/9.

+0

Может ли компилятор - при компиляции разделяемой библиотеки - предположить, что любое исключение, которое проходит через, и функция «extern C» не реализована? Потому что после этого он «входит» в программу ac, которая не регулируется стандартом C++, поэтому я немного неохотно принимаю это объяснение. – MikeMB

+0

@MikeMB Нет, потому что функция «extern» C «' может вызываться функцией C++ , 'gcc' (в отличие от' g ++ ') даже испускает пустые таблицы обработки исключений в библиотеках C, хотя я не знаю, нужны они или почему они необходимы. – Potatoswatter

+0

Итак, если в главном приложении не существует кода, связанного с исключениями (поскольку это C-приложение), а код внутри общей библиотеки не знает, будет ли кэширование или нет - как среда выполнения определяет, если он должен прекратить приложение или нет? Ответ, который основан исключительно на стандарте C++, является нехорошим, если говорить о кросс-язычном поведении и вещах, подобных разделяемым библиотекам, которые не входят в сферу применения стандарта C++. – MikeMB