我有一个非常简单的函数,调用time(2)
以获取纪元时间并将其作为未装箱的OCaml浮点数返回。
这里的平台是OS X 10.12.6,我使用OCaml版本4.03.0和4.04.0进行了测试。
以下是libunixtime.c
#define CAML_NAME_SPACE
#include <time.h>
#include <caml/memory.h>
#define IGNORE_UNUSED(x) ( (void)(x) )
CAMLprim double
ocaml_unixtime(value unit)
{
IGNORE_UNUSED(unit);
return (double) time(NULL);
}
OCaml代码unixtime.ml
看起来像这样......它返回一个未装箱的浮点数,并向编译器指示它不执行任何OCaml端分配。
这个函数只需要少于5个参数,所以看起来像实现它一次,并且对字节码编译器和本机编译器使用它应该没问题(https://caml.inria.fr/pub/docs/manual-ocaml/intfc.html#sec397)。
external unixtime : unit -> (float [@unboxed]) =
"ocaml_unixtime" "ocaml_unixtime" [@@noalloc];;
let () = Printf.printf "%f\n" (unixtime ())
此示例适用于本机编译器(尽管我有点担心转换为double
不是完全正确的事情,但它在我的机器上工作)
% ocamlopt unixtime.ml libunixtime.c
% ./a.out
1506195346.000000
但是,在使用字节码编译器进行编译并尝试运行时,我会立即得到段错误。
% ocamlc -custom unixtime.ml libunixtime.c
% ./a.out
Segmentation fault
Exit 139
字节码编译器不支持未装箱的浮点数吗?我如何弄清楚为什么字节码和本机编译器之间的行为不同?
答案 0 :(得分:3)
首先,您的代码似乎缺少对while ((new_socket = accept(s, (struct sockaddr*)&client, &c)) != INVALID_SOCKET)
值的CAMLparam
调用。这是必要的,以便GC了解它,请参阅section 19.1。
但还有另一个更重要的错误:字节码版本不能使用未装箱的函数(section 19.10),所以你必须为字节码编译器提供一个替代实现,它使用unit
返回一个盒装值。和caml_copy_double
。