【发布时间】:2018-09-30 04:33:17
【问题描述】:
我正在尝试使用使用 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)实现在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 丢失了。
...对吗?我在这里错过了什么......我可以使用罐装字符串,但这使得动态错误消息变得不可能。我也许可以使用静态 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