Исключения C++ безопасно распространят через код C?

У меня есть приложение C++, которое называет SQLite's (SQLite находится в C) sqlite3_exec (), который в свою очередь может назвать мою функцию обратного вызова реализованной в C++. SQLite компилируется в статическую библиотеку.

Если исключение выйдет из моего обратного вызова, то это распространит безопасно через код C SQLite к коду C++, звоня sqlite3_exec ()?

31
задан sharptooth 20 January 2010 в 12:49
поделиться

5 ответов

Я думаю, что это зависит от компилятора. Тем не менее, бросание исключения в обратном вызове было бы очень плохой идеей. Либо оно не будет работать без работы, либо код C в библиотеке SQLite не сможет обрабатывать его. Подумайте, что если это какой-то код в SQLite:

{
  char * p = malloc( 1000 );
  ...
  call_the_callback();  // might throw an exception
  ...
  free( p );
}

Если исключение «работает», код C не имеет возможности охватить его, а P никогда не будет освобожден. То же самое касается любых других ресурсов, которые могут выделить библиотеку.

29
ответ дан 27 November 2019 в 22:19
поделиться

Это не вариант. Вам придется p / вызывать функцию в DLL, которая была сгенерирована MASM или записана в неуправляемом C / C ++, используя встроенную сборку или внутрисину. Или используйте компилятор C ++ / CLI и генерируйте код смешанного режима с управлением #PRAGMA.

Остерегайтесь, что вы теперь больше не можете зависеть от компилятора JIT, генерируя любой код платформы для операционной системы. Используйте Project + Properties, создайте вкладку, цель платформы, чтобы заставить архитектуру соответствовать вашу неуправляемый код.

Посмотрите на CUDA для управляемого кода GPU.

-121--3339028-

, который был действительно интересным вопросом, и я проверял его из любопытства. На моей ОС X W / GCC 4.2.1 Ответ был да. Это работает отлично. Я думаю, что настоящий тест будет использовать GCC для C ++ и некоторых других (MSVC?, LLVM?) Для расставания C и посмотрим, работает ли она.

Мой код:

Callb.h:

#ifdef __cplusplus
extern "C" {
#endif

typedef void (*t_callb)();
void cfun(t_callb fn);

#ifdef __cplusplus
}
#endif

Callb.c:

#include "callb.h"

void cfun(t_callb fn) {
 fn();
}

main.cpp:

#include <iostream>
#include <string>
#include "callb.h"

void myfn() {
  std::string s( "My Callb Except" );
  throw s;
}

int main() {
  try {
    cfun(myfn); 
  }
  catch(std::string s) {
    std::cout << "Caught: " << s << std::endl;
  }
  return 0;
}
1
ответ дан 27 November 2019 в 22:19
поделиться

Если ваш обратный вызов вызывается из SQLite, из того же потока, из которого вы называете SQLite3_EXEC () a your qualthstack, должны быть пойманы более высоким уровнем.

Тестирование этого самостоятельно должно быть простым, нет?

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

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

0
ответ дан 27 November 2019 в 22:19
поделиться

SQLite ожидает, что вы вернете ошибку SQLite_abort на ошибку и код возврата 0 без ошибок. Таким образом, вы должны сделать завернуть весь обратный вызов C ++ в попытке поймать . Затем в Catch верните код ошибки SQLite SQLite_abort, в противном случае нулевой.

Проблемы будут возникать, если вы обходите возвращение через SQLite, так как он не будет освобожден / завершить код, который он выполняет после возвращения от вашего обратного вызова. Это приведет к неисследованным проблемам потенциально некоторые из которых могут быть очень неясными.

10
ответ дан 27 November 2019 в 22:19
поделиться

Уже есть протокол для обратного вызова, чтобы прервать вызов API. Из Документы :

Если возвращает обратный вызов sqlite3_exec () ненулевая, обычная, sqlite3_exec () Возвращает sqlite_abort, не вызывая обратный вызов снова и без бега любые последующие операторы SQL.

Я настоятельно рекомендую вам использовать это вместо исключения.

14
ответ дан 27 November 2019 в 22:19
поделиться