从 stdin\file 读取时的 OCaml 字符串长度限制
OCaml string length limitation when reading from stdin\file
作为我在大学学习的编译器原理课程的一部分,我们正在编写一个在 OCaml 中实现的编译器,它将 Scheme 代码编译成类似 CISC 的程序集(这只是 C 宏)。
编译器的基本操作是这样的:
- 读取
*.scm
文件并将其转换为 OCaml string
。
- 解析字符串并执行各种分析。
- 运行 语义分析器输出的 AST 上的代码生成器,将文本输出到
*.c
文件中。
- 使用 GCC 编译该文件并在终端中运行它。
嗯,一切都很好,除了这个:我正在尝试读取一个大约 4000 行长的输入文件,基本上是一个混合了 Scheme if
& and
。
我正在通过 utop
执行编译器。当我尝试读取输入文件时,我立即收到堆栈溢出错误消息。我最初猜测该文件对于 OCaml 来说太大了,但我找不到任何支持这一理论的文档。
有什么建议吗?
最大字符串长度由 Sys.max_string_length
给出。对于 32 位系统,它很短:16777211。对于 64 位系统,它是 144115188075855863。
除非您使用的是 32 位系统,并且您的 4000 行文件超过 16MB,否则我认为您没有达到字符串长度限制。
当字符串太长时,堆栈溢出不是您期望看到的。
更有可能的是你有无限递归,或者可能只是嵌套很深的计算。
嗯,事实证明限制是 OCaml 配置使用的最大 ram 的数量。
我运行在终端中执行以下命令以增加配额:
export OCAMLRUNPARAM="l=5555555555"
这太棒了 - 我几乎在瞬间就读取并编译了输入文件。
为了参考,这是读取文件的代码:
let file_to_string input_file =
let in_channel = open_in input_file in
let rec run () =
try
let ch = input_char in_channel in ch :: (run ())
with End_of_file ->
( close_in in_channel;
[] )
in list_to_string (run ());;
其中 list_to_string
是:
let list_to_string s =
let rec loop s n =
match s with
| [] -> String.make n '?'
| car :: cdr ->
let result = loop cdr (n + 1) in
String.set result n car;
result
in
loop s 0;;
有趣的是——我在尾递归中写了 file_to_string
。这防止了堆栈溢出,但由于某种原因进入了无限循环。哦,好吧...
作为我在大学学习的编译器原理课程的一部分,我们正在编写一个在 OCaml 中实现的编译器,它将 Scheme 代码编译成类似 CISC 的程序集(这只是 C 宏)。 编译器的基本操作是这样的:
- 读取
*.scm
文件并将其转换为 OCamlstring
。 - 解析字符串并执行各种分析。
- 运行 语义分析器输出的 AST 上的代码生成器,将文本输出到
*.c
文件中。 - 使用 GCC 编译该文件并在终端中运行它。
嗯,一切都很好,除了这个:我正在尝试读取一个大约 4000 行长的输入文件,基本上是一个混合了 Scheme if
& and
。
我正在通过 utop
执行编译器。当我尝试读取输入文件时,我立即收到堆栈溢出错误消息。我最初猜测该文件对于 OCaml 来说太大了,但我找不到任何支持这一理论的文档。
有什么建议吗?
最大字符串长度由 Sys.max_string_length
给出。对于 32 位系统,它很短:16777211。对于 64 位系统,它是 144115188075855863。
除非您使用的是 32 位系统,并且您的 4000 行文件超过 16MB,否则我认为您没有达到字符串长度限制。
当字符串太长时,堆栈溢出不是您期望看到的。
更有可能的是你有无限递归,或者可能只是嵌套很深的计算。
嗯,事实证明限制是 OCaml 配置使用的最大 ram 的数量。
我运行在终端中执行以下命令以增加配额:
export OCAMLRUNPARAM="l=5555555555"
这太棒了 - 我几乎在瞬间就读取并编译了输入文件。
为了参考,这是读取文件的代码:
let file_to_string input_file =
let in_channel = open_in input_file in
let rec run () =
try
let ch = input_char in_channel in ch :: (run ())
with End_of_file ->
( close_in in_channel;
[] )
in list_to_string (run ());;
其中 list_to_string
是:
let list_to_string s =
let rec loop s n =
match s with
| [] -> String.make n '?'
| car :: cdr ->
let result = loop cdr (n + 1) in
String.set result n car;
result
in
loop s 0;;
有趣的是——我在尾递归中写了 file_to_string
。这防止了堆栈溢出,但由于某种原因进入了无限循环。哦,好吧...