Подтвердить что ты не робот

StringBuilder для конкатенации строк выбрасывает OutOfMemoryException

В основном мы придерживаемся вышеуказанной передовой практики.

Посмотрите String vs StringBuilder

Но StringBuilder может выбросить OutOfMemoryException, даже если имеется достаточное количество памяти. Он выбрасывает исключение OOM, потому что ему нужен "непрерывный блок памяти".

Некоторые ссылки для справки StringBuilder OutOfMemoryException

и есть еще много...

Сколько из вас столкнулось с этой проблемой или осознало, и что вы сделали для ее решения?

Есть ли что-то, что мне не хватает?

P.S: Я не знал об этом.

Я перефразировал вопрос.

*** То же самое с ручным конкатенацией (я проверю это и обновит SO). Другая вещь, которая вызывала у меня беспокойство, заключалась в том, что в системе достаточно памяти. Это причина, по которой я поставил этот вопрос здесь, чтобы проверить, столкнулся ли кто-либо с этой проблемой или что-то не в порядке с кодом.

4b9b3361

Ответ 1

Строка underyling, которую вы создаете, также нуждается в непрерывном блоке памяти, потому что она представлена ​​в виде массива символов (массивы требуют непрерывной памяти). Если StringBuilder выбрасывает исключение OOM, вы не сможете создавать базовые без него.

Если создание строки вызывает OOM, скорее всего, в вашем приложении будет более серьезная проблема.

Изменить в ответ на пояснения:

Существует небольшое подмножество случаев, когда построение строки с помощью StringBuilder завершится неудачно, когда ручное конкатенация завершится успешно. Ручная конкатенация будет использовать точную длину, необходимую для объединения двух строк, в то время как StringBuilder имеет другой алгоритм для выделения памяти. Он более агрессивен и, скорее всего, выделяет больше памяти, чем это действительно необходимо для строки.

Использование StringBuilder также приведет к временному удвоению требуемой памяти, поскольку строка будет присутствовать в форме System.String и StringBuilder одновременно в течение короткого времени.

Но если один из способов вызывает OOM, а другой - нет, это, вероятно, указывает на более серьезную проблему в вашей программе.

Ответ 2

Если StringBuilder собирается выдать исключение OutOfMemoryException в вашей конкретной ситуации, то выполнение ручной конкатенации строк НЕ является лучшим решением; это намного хуже. Это именно так (создание чрезвычайно длинной строки), где предполагается использовать StringBuilder. Ручная конкатенация строки этого большого объема займет много раз память, создавая строку с помощью StringBuilder.

Тем не менее, на современном компьютере, если ваша строка запускает компьютер из смежной памяти, ваш дизайн глубоко, глубоко испорчен. Я не могу представить, что вы могли бы сделать, чтобы создать большую строку.

Ответ 3

Сколько памяти мы говорим? Я не говорю о свободной или полной памяти в системе, но как долго вы конкатенируете строку?

Исключение переполнения памяти почти всегда является очень плохим признаком вашего кода, даже если он терпит неудачу задолго до того, как на самом деле закончится память, как вы пережили из-за отсутствия постоянной памяти.

В этот момент вы должны действительно перестроить код.

Например, вот несколько способов борьбы с проблемой:

  • Не храните столько памяти в памяти за один раз, помещая его на диск или что-то в этом роде
  • Разделите его, сохраните список строковых/строковых построек и добавьте их до определенной длины перед переключением на новый, сохраняя проблему "непрерывной памяти".
  • Перестройте алгоритм, чтобы не создавать гигабайт данных в памяти вообще

Ответ 4

Если вы используете soclose для своих ограничений памяти, что это даже проблема, тогда вам, вероятно, следует подумать о другой архитектуре или получить более жесткую машину.

Ответ 5

Если вы посмотрите, как реализован StringBuilder, вы увидите, что на самом деле он использует String для хранения данных (String имеет внутренние методы, которые позволят StringBuilder изменять на месте).

т.е. они оба используют один и тот же объем памяти. Однако, поскольку StringBuilder автоматически расширяет базовый массив и при необходимости при необходимости копирует (но удваивает емкость), что, скорее всего, является причиной ошибки из памяти. Но, как уже отмечалось, оба из них требуют непрерывного блока памяти,

Ответ 6

Ну, на самом деле вопрос в том, зачем вам долго работать со строками? Если вы наткнетесь на эту проблему, более чем вероятно, вы должны изменить свою концепцию.

Эти проблемы влияют даже на класс System.String, поэтому вам следует скорее добавить свой список в List <string> и обрабатывать данные параллельно, что должно повысить общую производительность при правильном написании.

Ответ 7

Я столкнулся с этим исключением с очень большими строками, которые были построены с использованием различных строковых построек (что не должно было вызвать проблемы, поскольку они были объявлены в анонимных функциях), и, наконец, решил это, повторно используя один StringBuilder, объявленный вне анонимной функции.

Ответ 8

У меня был очень похожий опыт, когда я добавлял строки, но забыл добавить String.Format. Таким образом:

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

должен был быть:

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

Обратите внимание, что это мой код vb.net, который не удался. Я повторил аналогичный тест в С# с помощью:

myStringBuilder.Append('a', 1564544656);

против.

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

Но в моем случае vb.net вызвал у меня проблемы b/c неявных преобразований (я не мог параллель с той же самой проблемой в С#).

Я надеюсь, что это поможет кому-то.