2015-10-24 323 views
1

我在TCL中遇到以下問題。在我的應用程序中,我將很大的文本文件(幾百MB)讀入TCl列表中。該列表然後由函數返回到主要上下文,然後檢查是否爲空。下面是代碼快照:將列表轉換爲字符串 - TCL

set merged_trace_list [merge_trace_files $exclude_trace_file $trace_filenames ]

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

和我在 「如果」 行得崩潰。崩潰似乎與內存溢出有關。我認爲比較「」強制TCL將列表轉換爲字符串,並且由於字符串太長,導致崩潰。然後,我被另一個上面的「如果」行改爲:

if {[lempty $merged_trace_list]} {

和崩潰真的消失了。鑑於以上所述,我有幾個問題:

  1. TCL中允許的最大字符串長度是多少?
  2. 在內存分配方面,TCL中的字符串和列表有什麼區別?爲什麼我可以有很長的名單,但沒有相應的字符串?
  3. 當函數首次將列表返回到主作用域(第一行)時,是不是先轉換爲字符串?如果是的話,爲什麼我沒有在這一行中崩潰?

謝謝, 我希望描述和問題都很清楚。

康斯坦丁

回答

3

單個內存對象(例如字符串)的當前最大大小爲2GB。 這是一個在64位平臺上已知的(長期存在的)缺陷,但修復它需要顯着的ABI和API重大更改,所以直到Tcl 9.0纔會出現。

字符串和列表之間的區別在於字符串存儲在單個內存塊中,而列表存儲在指向元素的指針數組中。您可能在列表中獲得256k個元素沒有問題,但在此之後,當數組達到2GB限制時可能會遇到問題。

Tcl的值對象可能是同時有列表和字符串; Tcl關於「一切都是字符串」的說法實際上並不正確,只是將所有內容都序列化爲一個字符串。列表的返回不會強制將其轉換爲字符串 - 這實際上是一個相當慢的操作 - 但將值與字符串進行比較的結果是強制生成字符串。 lempty命令必須改爲獲取字符串的長度(您可以使用llength來執行相同的操作)並將其與零進行比較。


你可以調整你的程序,不需要一次保存所有的數據在內存中嗎?考慮到上面提到的錯誤,它有點危險。

+1

從好的方面來說,我們剛剛在本週舉行了一次會議,同意在Tcl 9.0上開始認真開發的策略;一旦我們獲得8.6.5的發佈,我們就會忙於此,並計劃在今年12月初。 –

+0

非常感謝!我從TCL學到了一些重要的東西。 – mkostya

1

這是不是一個真正的答案,但它是稍微太多的評論。

如果你想檢查列表是否爲空,最好的選擇是llength。如果列表長度爲0,則列表中沒有內容。對此的低級查找非常便宜。

如果您仍然想通過將列表與空字符串進行比較來確定列表是否爲空,您將不得不面對解析列表的字符串表示形式的成本。在這種情況下,$myLongList eq {}優於$myLongList == {},因爲後者的比較也會強制解釋器檢查操作數是否爲數字(至少它曾經是這樣的,它可能已經改變了)。

+0

我不記得如果我們在編譯時檢測到被比較的值之一是_definitely_非數字的情況下,我們是否優化了它。如果你想要一個列表清空的檢查,看看'llength'的值... –