OCaml本机代码上升堆栈溢出字符串

时间:2017-07-17 16:15:17

标签: ocaml stack-overflow native

我正在研究OCaml项目,该项目似乎存在一些计算效率问题。在试图找到瓶颈的同时,我尝试了编译本机代码而不是字节码的好奇心,想知道运行时间的差异有多大。

事实证明,本机代码会引发堆栈溢出。我尝试使用 OCAMLRUNPARAM = b 执行,但我没有获得有关堆栈跟踪的更多信息:

Fatal error: exception Stack overflow
Raised at file "map.ml", line 122, characters 10-25
Called from file "str.ml", line 259, characters 6-29

仅此而已。我不知道代码中导致它的重点是什么。此外,我的程序没有使用大字符串,所以我不明白为什么Str应该进行堆栈溢出...

我可以调整一些参数来调查问题吗?

3 个答案:

答案 0 :(得分:0)

溢出是由嵌套函数调用的深度引起的,而不是由所涉及的字符串的长度引起的。

除此之外,您没有提供足够的信息以提供帮助。你有一个名为" map.ml"的文件吗?在你的项目?第122行周围是什么样的?

如果您没有名为" map.ml"的文件。在您的项目中,您可能会看到标准库中函数的非尾递归行为。特别是,我猜测问题在于Str模块中正则表达式的编译。你有任何特别大的正则表达式吗?

答案 1 :(得分:0)

如果使用-g构建代码(例如,如果使用ocamlbuild,则在true: debug中添加_tags),您将在堆栈跟踪中获得代码的调试信息(如只反对标准库)。这应该会为您提供有关该问题的更多信息。

答案 2 :(得分:0)

OCAMLRUNPARAM控制OCaml解释器的堆栈大小,与编译代码无关,后者由操作系统加载程序运行,因此您需要使用操作系统来控制堆栈的大小。提示,在UNIX中,您可以使用ulimit来设置堆栈大小。

精确定位堆栈溢出源的问题是堆栈的默认大小允许如此大的跟踪,默认堆栈溢出打印机无法将其打印到源,因此诀窍实际上是限制堆栈大小,请参阅我的其他answer中的完整说明。

当然,此外,您需要(i)使用-g选项构建源代码,并且(ii)启用堆栈跟踪(取决于编译器版本和使用的库,它可能或可能默认情况下不启用)。前者特定于您的构建系统,后者可以通过设置OCAMLRUNPARAM=b环境变量(适用于字节码和本机代码)或通过在源代码中显式调用Printexc.record_backtrace true来完成,在申请开始时。

这些是一般性说明。在您的情况下,很可能地图调用导致堆栈溢出。在OCaml标准库中,List.map不是尾递归的,因此您可以考虑将所有List.map xs替换为List.rev (List.rev_map xs),或者仅使用List.rev_map替换,如果元素顺序为&n #39;重要。