簡體   English   中英

String連接的StringBuilder拋出OutOfMemoryException

[英]StringBuilder for string concatenation throws OutOfMemoryException

我們大多傾向於遵循上述最佳實踐。

看看String vs StringBuilder

但是, 即使有足夠的可用內存, StringBuilder也可能拋出OutOfMemoryException 它拋出OOM異常,因為它需要“連續的內存塊”。

一些鏈接供參考StringBuilder OutOfMemoryException

而且還有更多......

你們中有多少人遇到過這個問題或意識到你們做了什么來解決這個問題?

有什么我想念的嗎?

PS:我沒有意識到這一點。

我已經改寫了這個問題。

***同樣的事情與手動連接一起使用(我將驗證這一點並更新SO)。 引起我擔憂的另一件事是系統中有足夠的內存。 這就是我在這里提出這個問題的原因,以檢查是否有人遇到這個問題或者代碼有什么嚴重錯誤。

您創建的underyling字符串還需要一個連續的內存塊,因為它表示為chars數組(數組需要連續的內存)。 如果StringBuilder拋出一個OOM異常,那么如果沒有它,你將無法構建底層。

如果創建字符串會導致OOM,則應用程序中可能存在更嚴重的問題。

編輯以回應澄清:

有一小部分情況,當手動連接成功時,使用StringBuilder構建字符串將失敗。 手動連接將使用所需的確切長度以組合兩個字符串,而StringBuilder具有用於分配內存的不同算法。 它更具侵略性,可能會分配比字符串實際需要的內存更多的內存。

使用StringBuilder還會導致所需內存暫時加倍,因為字符串將在System.String形式和StringBuilder中同時存在一小段時間。

但是,如果一種方式導致OOM而另一種方式不是,那么它仍可能指向您的程序中更嚴重的問題。

如果StringBuilder將在您的特定情況下拋出OutOfMemoryException,那么進行手動字符串連接不是更好的解決方案; 這更糟糕。 這正是使用StringBuilder的情況(創建一個非常非常長的字符串)。 手動連接一個字符串這個大型將占用StringBuilder創建一個字符串所需的內存很多次。

也就是說,在現代計算機上,如果你的字符串在連續記憶中運行計算機,那么你的設計就會深深地存在深刻的缺陷。 我無法想象你可能會做什么會創建一個大的字符串。

我們談論了多少記憶? 我不是在談論系統中的空閑或總內存,但是你連接的字符串有多長?

內存溢出異常對於代碼來說幾乎總是一個非常糟糕的標志,即使它在內存實際耗盡之前很久就會失敗,就像你因為連續內存不可用而經歷過。

那時你應該重新構建代碼。

例如,以下是解決問題的各種方法:

  1. 不要一次在內存中保存盡可能多的數據,將其放在磁盤上或其他東西上
  2. 分解它,保留一個字符串/字符串構建器列表,並且在切換到新的字符串/字符串之前只添加一定長度,保持“連續內存”問題
  3. 重構算法,根本不在內存中建立千兆字節的數據

如果你正在運行soclose到你的記憶限制,這甚至是一個問題,那么你應該考慮一個不同的架構或獲得更強大的機器。

如果你看看StringBuilder是如何實現的,你會發現它實際上使用了一個String來保存數據( String有內部方法,這將允許StringBuilder在適當的位置進行修改)。

即它們都使用相同數量的內存。 但是,由於StringBuilder會在需要時自動擴展底層數組並根據需要進行復制(但容量加倍),這很可能是導致內存不足錯誤的原因。 但正如其他人已經指出這兩者都要求連續的內存塊,

那么,問題實際上是,為什么你需要使用那么長的字符串呢? 如果你偶然發現這個問題,你很可能會改變你的觀念。

這個問題甚至會影響System.String類,所以你應該把你的輸入組合成List <string>並並行處理數據,如果寫得正確,這應該會提高整體性能。

我遇到了這個異常,非常大的字符串與不同的字符串構建器一起構建(這不應該導致問題,因為它們是在匿名函數中聲明的),最后通過重用在匿名函數之外聲明的單個StringBuilder來解決它。

我有一個非常相似的經歷,我附加字符串,但忘了添加String.Format。 從而:

myStringBuilder.Append("1,""{0}""", someVeryLargeIntVariable)

本來應該:

myStringBuilder.Append(String.Format("1,""{0}""", someVeryLargeIntVariable))

請注意,這是我失敗的vb.net代碼。 我在c#中復制了一個類似的測試:

myStringBuilder.Append('a', 1564544656);

myStringBuilder.Append(string.Format("1,\"{0}\"", 1564544656));

但在我的情況下,vb.net讓我陷入了隱式轉換的麻煩b / c(我無法在c#中並行完全相同的問題)。

我希望能有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM