生成列表会导致堆栈溢出 [英] Generating a list causes a stack overflow

查看:128
本文介绍了生成列表会导致堆栈溢出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在生成一个随机数列表:

I'm generating a list of random numbers:

let gen n =
    let rec pom l n =
        match n with
        | 0 -> l
        | _ ->
            let el = Random.int 20000000
            in pom (el::l) (n-1)
    in
        pom [] n

let lo = gen 1000000

我得到的是

Fatal error: exception Stack_overflow

为什么?我正在使用尾递归(和累加器)

Why? I'm using tail recursion (and an accumulator)

编辑:

是的,两种堆栈都溢出.

You're right, the stack overflows on both sorts.

但是,如果我的代码有不计其数的行,用这种方式调试它会很痛苦.我想在这里使用ocamldebug,作为学习经验.我以这种方式运行ocamldebug:

But if my code had a zillion lines, it would be a pain to debug it this way. I'd like to use ocamldebug here, just as a learning experience. I ran ocamldebug this way:

(ocd) r
Loading program... done.
Time: 88089944
Program end.
Uncaught exception: Stack_overflow
(ocd) b
Time: 88089943 - pc: 52 - module Pervasives
214   | hd :: tl -> <|b|>hd :: (tl @ l2)
(ocd) bt
#0  Pc: 52  Pervasives char 7700
#1  Pc: 64  Pervasives char 7715
#2  Pc: 64  Pervasives char 7715
#3  Pc: 64  Pervasives char 7715
#4  Pc: 64  Pervasives char 7715
#5  Pc: 64  Pervasives char 7715
#6  Pc: 64  Pervasives char 7715
// and so it goes on forever

这没有告诉我为什么我的程序崩溃了.如何使用ocamldebug进行调试?

This tells me nothing why my program has crashed. How could I debug it with ocamldebug?

(元数据:我应该为此发布一个单独的线程还是应该留在这里)

推荐答案

由于错误是在另一个函数中,因此,这是将来可以更快地调试这种事情的方法.

Since the error was in a different function, here is how you can debug this kind of thing quicker in the future.

  1. 您可以打开回溯.请在以下内容的开头调用 Printexc.record_backtrace true 您的程序,或在环境变量OCAMLRUNPARAM设置为b的情况下运行它,如在OCAMLRUNPARAM=b ./a.out中一样.这应该告诉您错误发生在哪里,尽管有时它会跳过您希望成为调用堆栈的部分内容–我相信这是由于诸如内联之类的优化.不过,它通常很有用.为此,必须使用标志-g编译程序.

  1. You can turn on backtraces. Either call Printexc.record_backtrace true at the beginning of your program, or run it with the environment variable OCAMLRUNPARAM set to b, as in OCAMLRUNPARAM=b ./a.out. This should tell you where the error occurred, although sometimes it skips parts of what you would expect to be the call stack – I believe this is due to optimizations such as inlining. It is generally useful, though. For this, the program must have been compiled with the flag -g.

通过执行二进制搜索,即使在程序中的一堆函数调用中,您仍然可以找到异常的来源.首先将一半的函数调用包装在处理程序中.如果在那里发生异常,请解开它们,然后将它们中的一半再次包装在处理程序中,依此类推,直到深入到源代码为止.它仍然有些劳动密集型,但是您可以在O(log n)时间内以这种方式调试,而且不计其数的对数不多:)

You can still find the source of the exception, even in a bunch of function calls as in your program, by doing a binary search. First wrap half the function calls in a handler. If the exception occurs there, unwrap those, then wrap half of them in a handler again, and so on, until you drill down to the source. It is still somewhat labor intensive, but you can debug this way in O(log n) time, and the log of a zillion is not that much :)

这篇关于生成列表会导致堆栈溢出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆