【问题标题】:C interface: does failwith() leak memory?C 接口:failwith() 是否泄漏内存?
【发布时间】: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


    【解决方案1】:

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

    caml_failwith("float_of_string");
    

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-13
      • 2020-07-22
      • 2010-10-13
      • 2019-01-28
      • 2015-02-07
      • 1970-01-01
      相关资源
      最近更新 更多