Stackoverflow与专门的Hashtbl(通过Hashtbl.make)

时间:2011-07-20 05:48:00

标签: hashtable ocaml stack-overflow

我正在使用这段代码并且将触发stackoverflow,如果我使用Extlib的Hashtbl,则不会发生错误。有没有stackoverflow使用专门的Hashtbl的任何提示?

module ColorIdxHash = Hashtbl.Make(
  struct
    type t = Img_types.rgb_t
    let equal = (==)
    let hash = Hashtbl.hash
  end
)
(* .. *)
let (ctable: int ColorIdxHash.t) = ColorIdxHash.create 256 in
    for x = 0 to width -1 do
      for y = 0 to height -1 do
        let c = Img.get img x y in
        let rgb = Color.rgb_of_color c in
          if not (ColorIdxHash.mem ctable rgb) then ColorIdxHash.add ctable rgb (ColorIdxHash.length ctable)
      done
    done;
(* .. *)

回溯指向hashtbl.ml:

  

致命错误:异常Stack_overflow在文件“hashtbl.ml”处引发,   第54行,字符16-40从文件“img / write_bmp.ml”,行调用   150,字符52-108 ......

任何提示?

2 个答案:

答案 0 :(得分:5)

嗯,您正在使用物理相等(==)来比较哈希表中的颜色。如果颜色是结构化值(我无法从这段代码中得知),它们中的任何一个都不会在物理上彼此相等。如果所有颜色都是不同的对象,它们都将进入表格,这可能是相当多的对象。另一方面,散列函数将基于实际颜色R,G,B值,因此可能存在大量重复。这意味着您的哈希桶将具有非常长的链。也许某些内部函数不是尾递归,因此堆栈溢出。

通常,最长链的长度为2或3,因此不会经常出现此错误也不足为奇。

查看我的hashtbl.ml(OCaml 3.12.1)的副本,我在第54行看不到任何非尾递归的东西。所以我的猜测可能是错的。在第54行,为哈希表分配新的内部数组。所以另一个想法就是你的哈希表太大了(可能是由于不必要的重复)。

要尝试的一件事是使用结构相等(=)并查看问题是否消失。

答案 1 :(得分:1)

如果您的类型包含循环值,则可能出现非终止或堆栈溢出的一个原因。 (==)将终止于循环值(虽然(=)可能不会),但Hash.hash可能不是循环安全的。因此,如果您操作类型Img_types.rgb_t的循环值,则必须设计一个循环安全散列函数 - 通常只在值的一个非循环子字段/子组件上调用Hash.hash

过去我已经被这个问题所困扰了。追踪并不是一个有趣的错误。

相关问题