我在TCL遇到了以下问题。在我的应用程序中,我将非常大的文本文件(几百MB)读入TCl列表。然后该函数将该列表返回到主上下文,然后检查空白。这是代码快照:
set merged_trace_list [merge_trace_files $exclude_trace_file $trace_filenames ]
if {$merged_trace_list == ""} {
...
我在"如果"线。崩溃似乎与内存溢出有关。我认为与""的比较强制TCL将列表转换为字符串,由于字符串太长,这会导致崩溃。然后我替换了上面的"如果"换另一个:
if {[lempty $merged_trace_list]} {
崩溃确实消失了。鉴于上述情况,我有几个问题:
谢谢, 我希望描述和问题都清楚。
康斯坦丁
答案 0 :(得分:3)
单个内存对象(例如,字符串)的当前最大大小为2GB。 这是64位平台上的一个已知错误(长期存在),但修复它需要进行重大的ABI和API更改,因此在Tcl 9.0之前不会出现。
字符串和列表之间的区别在于字符串存储在单个内存块中,而列表存储在指向元素的指针数组中。您可以在列表中获得256k元素没问题,但在此之后,当阵列达到2GB限制时,您可能会遇到问题。
Tcl的值对象可以同时同时包含列表和字符串;关于Tcl的“一切都是字符串”的格言并不是真的,只是所有东西都可以序列化为字符串。返回列表不会强制它转换为字符串 - 这实际上是一个相当慢的操作 - 但是将相等的值与字符串进行比较会强制生成字符串。 lempty
命令必须改为获取字符串的长度(您可以使用llength
执行相同的操作)并将其与零进行比较。
您是否可以将程序调整为不需要立即将所有数据保存在内存中?考虑到上面提到的错误,它的生活有点危险。
答案 1 :(得分:1)
这不是一个真正的答案,但对评论来说有点太多了。
如果要检查列表是否为空,则最佳选项为llength
。如果列表长度为0,则列表中没有内容。对此的低级查找非常便宜。
如果您仍想通过将列表与空字符串进行比较来确定列表是否为空,则必须面对解析列表的字符串表示的成本。在这种情况下,$myLongList eq {}
优于$myLongList == {}
,因为后者的比较也会强制解释器检查操作数是否为数字(至少它曾经是这样,它可能已经改变了)。 / p>