Я пытаюсь работать с интерфейсом C, созданным с помощью camlidl.Библиотека, с которой я работаю, возвращает код ошибки, выделяя и заполняя аргумент in / out char* error_message
и возвращая его.После вызова функции я проверяю код ошибки на ненулевое ... если true, я вызываю caml_failwith(error_message)
, чтобы вызвать исключение OCaml, используя сообщение об ошибке библиотеки.
Однако я начал копать немного,потому что генерирование исключения выглядит так, как будто оно завершает функцию и никогда не освобождает сообщение об ошибке.Рассмотрим этот фиктивный код:
/* in the C stub function call... */
double _res;
int error = 0;
char* error_message = NULL;
// if this function errors, it will set error to non-zero
// and strdup something into error_message
_res = call_library_function(&error, error_message);
if (error) {
caml_failwith(error_message);
free(error_message); // NEVER CALLED?
}
/* code to copy result to an OCaml value and return */
Реализация исключений func caml_failwith(s)
находится в runtime/fail_*.c
, но в основном она просто вызывает caml_raise_with_string
, то есть:
CAMLparam1(tag);
value v_msg = caml_copy_string(msg);
caml_raise_with_arg(tag, v_msg);
CAMLnoreturn;
Итак,он копирует строку в значение OCaml с помощью caml_copy_string, а затем поднимает аргумент ar-no-return.Короче говоря, error_message потеряно .
... Верно?Что мне здесь не хватает ... Я мог бы использовать консервированные строки, но это делает невозможным динамические сообщения об ошибках.Возможно, я мог бы использовать статический символ *, хотя это уже не безопасно для многопоточных приложений. Есть ли способ вызвать caml_failwith
, используя простую старую динамику char*
, и не вызывать утечку?
РЕДАКТИРОВАТЬ: Я подумал об одном решении...
char error_message_buf[100] = {'\0'};
double _res;
// ... rest of local vars and service call ...
if (error) {
strncpy(error_message_buf, error_message, 99)
free(error_message);
caml_failwith(error_message_buf);
}
... но уродливый человек.strncpy
в стек, чтобы просто развернуться и caml_copy_string
снова?Кроме того, он устанавливает жестко ограниченную длину сообщения об ошибке.Тем не менее, если это единственный способ не просочиться ...