列表到字符串的转换 - TCL

Conversion of list to string - TCL

我在TCL遇到了以下问题。在我的应用程序中,我将非常大的文本文件(大约数百 MB)读入 TCl 列表。该列表然后由函数返回到主上下文,然后检查是否为空。这是代码快照:

set merged_trace_list [merge_trace_files $exclude_trace_file $trace_filenames ]

if {$merged_trace_list == ""} { ...

我在 "if" 行崩溃了。崩溃似乎与内存溢出有关。我认为与“”的比较会强制 TCL 将列表转换为字符串,并且由于字符串太长,这会导致崩溃。然后我用另一行替换了上面的 "if" 行:

if {[lempty $merged_trace_list]} {

崩溃确实消失了。综上所述,我有几个问题:

  1. TCL 允许的最大字符串长度是多少?
  2. TCL中string和list在内存分配上有什么区别?为什么我可以有很长的列表,却没有相应的字符串?
  3. 当函数第一次返回的列表进入主作用域时(第一行),是不是先转换成字符串?如果是,为什么我在那行没有崩溃?

谢谢, 我希望描述和问题都清楚。

康斯坦丁

这不是一个真正的答案,但对于评论来说有点太多了。

如果要检查列表是否为空,最好的选择是llength。如果列表长度为 0,则您的列表没有内容。对此的低级查找非常便宜。

如果您仍想通过将列表与空字符串进行比较来确定列表是否为空,则您将不得不面对解析列表的字符串表示形式的成本。在这种情况下,$myLongList eq {}$myLongList == {} 更可取,因为后者的比较还强制解释器检查操作数是否为数字(至少以前是这样,它可能已经改变了)。

单个内存对象(例如字符串)的当前最大大小为 2GB。 这是 64 位平台上的一个已知错误(长期存在),但修复它需要重要的 ABI 和 API 重大更改,因此直到 Tcl 才会出现9.0.

字符串和列表的区别在于字符串存储在单个内存块中,而列表存储在指向元素的指针数组中。您可能可以在列表中获取 256k 个元素没问题,但之后您可能 运行 遇到问题,因为数组达到 2GB 限制。

Tcl 的值对象可能同时是 列表和字符串;关于 Tcl 的格言“一切都是字符串”实际上并不正确,只是一切都可以序列化为字符串。列表的返回不会强制将其转换为字符串——这实际上是一个相当慢的操作——但是将相等的值与字符串进行比较 确实 强制生成字符串。 lempty 命令必须改为获取字符串的长度(您可以使用 llength 来做同样的事情)并将其与零进行比较。


您能否调整您的程序,使其不需要一次将所有数据保存在内存中?上面提到的bug,它的生活有点危险。