Использование setjmp и longjmp в C при связывании с библиотеками C++

Я хотел бы использовать setjmp и longjmp в программе C, которая ссылается на библиотеку, реализованную на C++ (но имеющую C API).

Код C++ выполняет динамическое выделение памяти, а указатели передаются через API, но пока сторона C кода правильно управляет этими (непрозрачными) объектами, при использовании longjmp не должно быть никаких проблем, верно?

Я знаю, что использовать эти функции в коде C++ небезопасно, но должно ли это быть безопасно в коде C, связанном с кодом C++?


person Posco Grubb    schedule 31.08.2011    source источник


Ответы (3)


Тот факт, что вы вызываете функции C++ из своего кода C, не делает setjmp и longjmp более небезопасными, чем они всегда были.

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

person Miguel    schedule 31.08.2011
comment
В порядке. Я думаю, что до тех пор, пока эти распределения, сделанные в библиотеке C++, могут быть очищены с помощью соответствующих вызовов C-интерфейса, код C++ изолирован от эффектов longjmp, а обработка исключений и longjmp не могут мешать каждому. разное. (Я также являюсь разработчиком библиотеки C++.) - person Posco Grubb; 01.09.2011
comment
Если у вас есть обработка исключений в библиотеке С++, вы должны убедиться, что любые выброшенные исключения перехватываются внутри библиотеки, вы не хотите, чтобы исключения выходили из вашего кода С++ (не уверен, что произойдет, если вы это сделаете, никогда не пробовал) . А для высвобождения выделений C++ вам придется выяснить, что нужно высвободить из кода C, который берет на себя управление после вызова longjmp. Поскольку вы владеете приложением и библиотекой, я не вижу никаких проблем, чтобы заставить это работать. - person Miguel; 01.09.2011

setjmp/longjmp, как правило, не безопасны для использования с C++. Они эффективно воспроизводят поведение исключений, но без правильной раскрутки стека (например, они не будут запускать деструкторы для объектов в кадрах стека, которые они принудительно покидают). По возможности используйте исключения, если они у вас есть.

person Community    schedule 31.08.2011
comment
OP не пытается использовать setjmp/longjmp в C++, а скорее программу C, которая использует некоторый код C++ через интерфейс C (который предположительно маскирует все C++-измы в код, вызываемый как C, и делает это безопасно). - person Chris Lutz; 31.08.2011
comment
Даже тогда, это зависит. Вероятно, было бы безопасно перейти в ваш собственный код, но использование longjmp для выхода из обратного вызова (например) может вызвать хаос. - person ; 31.08.2011
comment
Использование longjmp для выхода из обратного вызова (если на это явно не дано разрешение) звучит как плохая идея, независимо от языка. Вы также должны убирать за собой в C. - person Chris Lutz; 31.08.2011
comment
@duskwuff Хорошо, использовать его в обратном вызове опасно, но это было бы так, если бы я не смешивал языки. Кроме этого, есть ли другие случаи, которые заставляют вас говорить, что это зависит? - person Posco Grubb; 01.09.2011

Ну правильно и не правильно. longjmp обычно не вызывает деструкторы, поэтому используйте его в коде, подобном следующему:

void f(jmp_buf jb)
{
  some_cpp_object_with_a_nontrivial_destructor x;
  if (some_condition) longjmp(jb, 2);
  // some other code
}

произведет все виды плохих вещей. Если вы избегаете таких ситуаций, вы должны быть в порядке. (Вообще, longjmp не должен переходить через какие-либо активные кадры стека с объектами, имеющими нетривиальные деструкторы.)

person zvrba    schedule 31.08.2011
comment
Мой код написан на C, поэтому я не могу определить локальные переменные с типом, у которого есть конструктор. Поэтому ваш пример не применим к моему вопросу. - person Posco Grubb; 01.09.2011
comment
Вы окажетесь в очень похожем сценарии, если сделаете обратный вызов функции C++, а обратный вызов вызовет longjmp. - person zvrba; 01.09.2011