2017-01-30 9 views
1

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

答えて

3

あなたprint_block機能がCAMLparam1()ので、それはCAMLreturn0を返す必要がありますを使用していますご協力いただきありがとうございます使用しています。私はこれがあなたの問題だとは思っていません。ただ気がついたことです。しかし、それは問題かもしれません。

+0

実際、それは私の問題でした。私はそれが間違った機能だったので、それを見落としました。どうもありがとう ! –

関連する問題