首页 > 解决方案 > C 接口:failwith() 是否泄漏内存?

问题描述

我正在尝试使用使用 camlidl 生成的 C 接口。我正在使用的库通过分配和填充输入/输出参数char* error_message并返回它来返回错误代码。在函数调用之后,我检查错误代码是否非零......如果为真,我调用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 */

异常 funccaml_failwith(s)实现是 in runtime/fail_*.c,但它基本上只是调用caml_raise_with_string,即:

CAMLparam1(tag);
value v_msg = caml_copy_string(msg);
caml_raise_with_arg(tag, v_msg);
CAMLnoreturn;

因此,它使用 caml_copy_string 将字符串复制到 OCaml 值,然后引发 arg 并且不返回。简而言之,error_message is lost

...正确的?我在这里错过了什么......我可以使用罐装字符串,但这使得动态错误消息变得不可能。我也许可以使用静态 char*,尽管如果没有大量工作,它就不再是线程安全的了。 有什么方法可以调用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?另外,它设置了错误消息长度的硬编码上限。不过,如果这是不泄漏的唯一方法......

标签: ocaml

解决方案


caml_failwith()被设计成你可以用一个常量字符串来调用它,这是一种非常常见的情况:

caml_failwith("float_of_string");

所以,你不能指望它释放它的论点。

我个人不认为这是空间泄漏,这只是功能的设计方式。

您首先复制消息的解决方案对我来说似乎是合理的(而且不是特别难看)。

(本质上,这就是我多年前从 C 切换到 OCaml 的原因。)


推荐阅读