Debugging 调试OCaml程序内部外部命令的内存使用

Debugging 调试OCaml程序内部外部命令的内存使用,debugging,memory-leaks,ocaml,Debugging,Memory Leaks,Ocaml,我在一个无法隔离的程序中遇到内存问题。我想知道调试它的最佳策略是什么 我的程序在运行与此类似的行时会耗尽可用内存: Sys.command“solver file.in>file.out” 错误消息是: 致命错误:异常系统错误(“solver file.in>file.out:无法分配内存”) 出错前,程序运行约15秒,消耗超过1GB的RAM,直到最后死机 但是,在shell中运行完全相同的命令行(使用相同的输入文件)只需要0.7秒,并且使用的RAM少于10 MB 似乎有什么东西正在泄漏大量的内

我在一个无法隔离的程序中遇到内存问题。我想知道调试它的最佳策略是什么

我的程序在运行与此类似的行时会耗尽可用内存:

Sys.command“solver file.in>file.out”

错误消息是:

致命错误:异常系统错误(“solver file.in>file.out:无法分配内存”)

出错前,程序运行约15秒,消耗超过1GB的RAM,直到最后死机

但是,在shell中运行完全相同的命令行(使用相同的输入文件)只需要0.7秒,并且使用的RAM少于10 MB

似乎有什么东西正在泄漏大量的内存,但我无法识别它。试图通过在新的OCaml文件中复制错误来隔离错误会导致类似于在shell中直接运行错误的情况

作为参考,
file.in
file.out
(在shell中运行命令时预期的结果文件)都大约有200KB大

我尝试使用
Unix.system
而不是
Command.sys
,但没有发现任何差异


我想知道
Sys.command
是否有一些已知的内存限制(例如,内存使用过多),以及确定外部程序行为变化如此剧烈的最佳方法是什么。

Sys.command
只是从C库调用
system()
。问题出现在
system()
的薄型包装中的可能性非常小

在这两种情况下,流程上下文的某些方面很可能是不同的

我要尝试的第一件事是向
解算器
代码添加少量跟踪,以了解失败案例中发生的情况

如果您没有解算器的源,您可以尝试重新创建似乎有效的环境。以下内容可能值得一试:

Sys.command "/bin/bash -l -c 'solver file.in > file.out'"
这取决于bash的可用性。
-l
标志告诉bash假装它是一个登录shell。如果你没有bash,你可以尝试类似的shell

更新

好的,在运行解算器之前,OCaml代码中似乎发生了内存膨胀。所以问题不在于解决者

如果不了解更多关于OCaml代码的信息,很难说它是否消耗了合理的内存量

从表面上看,这听起来不像是堆栈空间用完了,所以我不会马上担心缺少尾部递归。通常这是需要考虑的事情

实际上,这听起来很像是一个无限回归,在这个过程中内存被分配。无论是否打开交换,这最终都会耗尽内存空间


如果您的代码在您试图解决的任何问题的一个小示例上运行,您可以排除这种情况。在这种情况下,您可能需要重新设计解决方案以节省内存。

遵循Jeffrey Scofield的建议后,我意识到内存不足问题发生在调用解算器之前,尽管出现了错误消息

使用以下简单的OCaml文件和Bash脚本进行确认(需要根据系统中的可用内存调整矩阵尺寸):

test.ml:

let _ = 
  let _ = Array.create_matrix 45000 5000 0 in
  Sys.command "./test.sh"
test.sh:

#!/bin/bash

for x in {1..20000};do :;done
使用一个脚本来测量内存使用情况(比如一个),我已经能够确认,虽然Bash脚本在我的机器上使用的内存不超过5 MB,并且原始程序的峰值超过1.7 GB,但显示的错误消息似乎将错误与
Sys.command
行相关联,尽管这在实践中是极不可能的


换句话说,要调试外部命令的内存使用情况,最好确保实际调用了外部进程,否则错误消息可能会产生误导。

您确定调用的是同一个
解算器吗?好建议,我将解算器调用包装在Bash脚本中,我意识到解算器从未真正被调用过。相反,内存分配错误发生在调用解算器之前,但发生在
Sys.command
调用之前的一行之后,该行包含正确输出的
printf
。似乎在实际调用
Sys.command
之前,内存中分配了一些繁重的内容。我将尝试看看那里发生了什么。似乎解算器确实可以运行,但由于某种不太可能的巧合,或者由于OCaml的垃圾收集器在内存不足期间的行为,解算器进程所需的少量6MB在运行时不可用,这仅仅是因为OCaml进程正在使用剩余的内存。我会发现我的内存不太可能完全被OCaml进程占用,但我似乎已经停用了我机器上的交换空间。当内存不足时,您认为这会导致一些问题吗?