我正在尝试在C库和Ocaml程序之间创建绑定。我在与Gc接口时遇到了问题。 我制作了一个小程序来复制我的问题。 目标是将在C程序中分配的custom_block传递给Ocaml中的主程序,并将C结构上的指针包含在内。 然后,我试图在清理之前使用它(只是在示例中打印一个值)(我强制调用GC)。
在ocaml下面的主程序中,我可以对该行进行注释" my_print_block"或者" Gc.compact()"并且一切正常。指针的地址是正确的,我可以打印该值并调用析构函数来释放C分配的指针。 但是当两者被激活时,我会遇到分段错误。
Mail.ml
type ptr
external create_block: String.t -> ptr = "create_block"
external print_block: ptr -> unit = "print_block"
let my_print_block x :unit =
print_block x;
()
let main () =
let z = create_block "2.4" in
let _ = my_print_block z in
let () = Gc.compact () in
()
let _ = main ()
Interface.c
#include <caml/mlvalues.h>
#include <caml/memory.h>
#include <caml/alloc.h>
#include <caml/custom.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct foo
{
float x;
};
void local_destroy(value v)
{
struct foo* p = *((struct foo**)Data_custom_val(v));
printf( "freeing p now (%p)\n with *p=%f \n", p, p->x );
fflush(stdout);
free(p);
}
static struct custom_operations ops = {
"ufpa custom_operations",
local_destroy,
custom_compare_default, //default function, should not be used
custom_hash_default, //default function, should not be used
custom_serialize_default, //default function, should not be used
custom_deserialize_default, //default function, should not be used
custom_compare_ext_default //default function, should not be used
};
void print_block(value type_str)
{
CAMLparam1(type_str);
struct foo* p = *( (struct foo**)Data_custom_val(type_str));
printf("value float = %f\n", p->x);
}
CAMLprim value create_block(value type_str)
{
CAMLparam1(type_str);
//retrieving str and creating a float value
char* fval = String_val(type_str);
float val = atof(fval);
//creating and allocating a custom_block
CAMLlocal1(res);
res = alloc_custom(&ops, sizeof(struct foo*), 10, 100);
//creating and allocating a struct pointer
struct foo* ptr = malloc(sizeof(struct foo));
printf("allocating : %p\n", ptr);
ptr->x = val;
//copying the pointer itself in the custom block
memcpy(Data_custom_val(res), &ptr, sizeof(struct foo*));
CAMLreturn(res);
}
生成文件
main.native: interface.c main.ml
rm -rf _build
rm -f main.native main.byte
ocamlbuild -cflags -g interface.o
ocamlbuild -lflag -custom -cflags -g -lflags -g main.byte -lflags interface.o
#ocamlbuild -cflags -g -lflags -g main.native -lflags interface.o
使用ocamldebug,程序似乎在my_print_block上崩溃,但我无法从跟踪中提取更多感觉。
使用gdb,错误位于Gc
中#0 0x000000000040433d in caml_oldify_one ()
#1 0x0000000000406060 in caml_oldify_local_roots ()
#2 0x000000000040470f in caml_empty_minor_heap ()
#3 0x00000000004141ca in caml_gc_compaction ()
#4 0x000000000041bfd0 in caml_interprete ()
#5 0x000000000041df48 in caml_main ()
#6 0x000000000040234c in main ()
我已经看过几个例子,我在https://caml.inria.fr/pub/docs/manual-ocaml/intfc.html阅读了有关C绑定的文档,但我无法弄清楚我做错了什么。我使用的是ocaml version4.04.0 + flambda
感谢您的帮助
答案 0 :(得分:3)
您的<html><body bgcolor="white">
<h1>Dissociation</h1>
<p><b>Artist: </b>Dillinger Escape Plan</p>
<table>
<tr bgcolor="linen">
<td>Limerent Death</td>
<td>4:06</td>
</tr>
<tr bgcolor="linen">
<td>Symptom Of Terminal Illness</td>
<td>4:03</td>
</tr>
<tr bgcolor="linen">
<td>Wanting Not So Much To As To</td>
<td>5:23</td>
</tr>
</table>
</body></html>
函数使用print_block
,因此它应该以{{1}}返回。我不确定这是你的问题,这只是我注意到的事情。但这可能是问题所在。