OCAMLRUNPARAM不会影响堆栈大小

kli*_*ist 5 stack-overflow ocaml

我想改变我的堆栈大小,以允许具有许多非尾递归函数的项目在更大的数据上运行.为此,我尝试设置OCAMLRUNPARAM="l=xxx"不同的xxx值(在0到10G范围内),但它没有任何效果.设置OCAMLRUNPARAM甚至是正确的方法吗?

如果它是相关的:我感兴趣的项目是使用OCamlMakefile,target构建的native-code.

这是一个最小的例子,只是创建一个没有尾递归的大型列表.要快速检查OCAMLRUNPARAM的设置是否有效,我编译了程序stacktest.ml:

let rec create l =
  match l with
| 0 -> []
| _ -> "00"::(create (l-1))

let l = create (int_of_string (Sys.argv.(1)))
let _ = print_endline("List of size " ^ string_of_int (List.length l) ^ " created.")
Run Code Online (Sandbox Code Playgroud)

使用命令

ocamlbuild stacktest.native
Run Code Online (Sandbox Code Playgroud)

并通过以下bash脚本通过(或多或少)二进制搜索大致发现堆栈溢出发生在列表的哪个长度foo.sh:

#!/bin/bash
export OCAMLRUNPARAM="l=$1"
increment=1000000
length=1
while [[ $increment > 0 ]] ; do
    while [[ $(./stacktest.native $length) ]]; do
        length=$(($length+$increment))
    done
    length=$(($length-$increment))
    increment=$(($increment/2))
    length=$(($length+$increment))
done
length=$(($length-$increment))
echo "Largest list without overflow: $length"
echo $OCAMLRUNPARAM
Run Code Online (Sandbox Code Playgroud)

结果在这个脚本的运行之间有所不同(并且中间结果在一次运行中甚至不一致,但是现在让我们忽略它),但无论我是否打电话它们都是相似的

bash foo.sh 1
Run Code Online (Sandbox Code Playgroud)

要么

bash foo.sh 1G
Run Code Online (Sandbox Code Playgroud)

即堆栈大小是否设置为1或2 ^ 30个字.

ivg*_*ivg 7

通过OCAMLRUNPARAM更改堆栈限制仅适用于由OCaml解释器运行的字节码可执行文件.本机程序由操作系统处理并直接在CPU上执行.因此,为了更改堆栈限制,您需要使用操作系统提供的工具.

例如,在Linux上有ulimit一个处理许多进程参数的命令,包括堆栈限制.将以下内容添加到脚本中

ulimit -s $1
Run Code Online (Sandbox Code Playgroud)

你会看到结果正在发生变化.