在从C回调期间保护次要堆上的指针

时间:2014-05-06 08:52:27

标签: c garbage-collection ocaml

我有一个场景,其中C库以float array作为参数,并且(在某个地方的某个地方)调用OCaml函数:

    -------------
    | a) OCaml  |   p : value (float array)
    -------------
        ||          
        \/
    ---------
    | b) C  |       p : double*
    ---------
        ||          
        \/
    ------------
    | c) OCaml |    p : value (float array)
    ------------

原则上,由于OCaml的智能内存布局,人们可以直接将value作为double*传递到C库中,而一切只是工作(TM)。也就是说,直到部分c)中发生了一些分配。

当GC决定清理次要堆时,double *指针可能变为无效。由于这只能发生在b)中的参数中,我想发信号通知GC“做你想做的任何事情,但在我告诉你之前不要移动这些块中的内容”。有没有办法使用OCaml API实现这一目标?

3 个答案:

答案 0 :(得分:1)

一个bigarray将是解决这个问题的正确方法,但这意味着你不能只将double *指针从C传递给OCaml,你必须跟踪代表bigarray的自定义块。 / p>

还有另外一种方法,虽然它不那么优雅且不那么健壮:你可以通过执行以下两项来确保float array不会移动:

  1. 在分配(征集Gc.minor
  2. 后的某个时刻强制收集
  3. 禁止压缩(使用Gc.setmax_overhead设置为1000000)

答案 1 :(得分:0)

您可以按照manual中的说明创建自定义功能块。但我建议你一个更好的解决方案。考虑使用Bigarrays。

答案 2 :(得分:0)

如果您希望GC跟踪您的本地值,您应该使用CAMLparam *声明,例如CAMLparam1(p)而不是double *p

这将允许GC更新您的值指针并确保其安全。

您仍然可以通过double*诀窍将p复制到具有正确胁迫的double* p2中,您只需要做两次:

  1. 在你的职能开始时。
  2. 回调后。
  3. 所以你的代码看起来像那样:

    value myfunction (value p_v)
    {
     CAMLparam1(p_v);
     double *p = (double*) p_v;
    
     /* actions over p */
    
     callback(p_v);
     p = (double*) p_v;
    
     /* remainder of your code */
    
     CAMLreturn (value_to_return);
    }
    

    有关良好的GC互动的更多信息,请阅读OCaml manual