CライブラリとOcamlプログラム間のバインディングを作成しようとしています。私はGcとのインターフェイスに問題が発生しました。 問題を再現するための小さなプログラムを作った。 目的は、Cプログラムに割り当てられ、C構造体のポインタを含むcustom_blockをOcamlのメインプログラムに渡すことです。 その後、クリーニング(私はGCへの呼び出しを強制的に)の前にそれを使用しようとしています(例では値を表示しています)。Ocaml:Cポインタを含むカスタムブロックを使用しているときのGCでのsegfault
ocamlの下のメインプログラムでは、「my_print_block」行または「Gc.compact()」行をコメントすることができ、すべて正常に動作します。ポインタのアドレスが正しい場合は、デストラクタはCの割り当てられたポインタを解放するために呼び出されます。 しかし、2つがアクティブになると、私はセグメンテーションフォルトを取得します。 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);
}
Makefileの
ocamldebugで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
、プログラム
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
が
実際、それは私の問題でした。私はそれが間違った機能だったので、それを見落としました。どうもありがとう ! –