Интерфейс C: failwith () утечка памяти? - PullRequest
0 голосов
/ 30 сентября 2018

Я пытаюсь работать с интерфейсом 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 снова?Кроме того, он устанавливает жестко ограниченную длину сообщения об ошибке.Тем не менее, если это единственный способ не просочиться ...

1 Ответ

0 голосов
/ 30 сентября 2018

caml_failwith() разработан так, что вы можете вызывать его с помощью константной строки, что является очень распространенным случаем:

caml_failwith("float_of_string");

Таким образом, вы не можете ожидать, что он освободит свой аргумент.

Лично я не считаю это утечкой места, это просто то, как устроена функция.

Ваше решение сначала скопировать сообщение кажется мне разумным (и не особенно уродливым).

(Именно поэтому я и перешел с C на OCaml много лет назад.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...