OutOfMemoryException в регулярных выражениях. Соответствует при обработке больших файлов. - PullRequest
3 голосов
/ 07 апреля 2009

Я получил журнал исключений из одного из выпусков производственного кода.

System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
   at System.Text.RegularExpressions.Match..ctor(Regex regex, Int32 capcount, String text, Int32 begpos, Int32 len, Int32 startpos)
   at System.Text.RegularExpressions.RegexRunner.InitMatch()
   at System.Text.RegularExpressions.RegexRunner.Scan(Regex regex, String text, Int32 textbeg, Int32 textend, Int32 textstart, Int32 prevlen, Boolean quick)
   at System.Text.RegularExpressions.Regex.Run(Boolean quick, Int32 prevlen, String input, Int32 beginning, Int32 length, Int32 startat)
   at System.Text.RegularExpressions.MatchCollection.GetMatch(Int32 i)
   at System.Text.RegularExpressions.MatchEnumerator.MoveNext()

Данные, которые он пытается обработать, занимали около 800 КБ.

В моих локальных тестах все работает отлично. Вы когда-нибудь видели подобное поведение, в чем может быть причина?

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

Мои регулярные выражения:

РЕДАКТИРОВАТЬ 2:

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

((?:( |\.\.|\.|""|'|=)[\/|\?](?:[\w#!:\.\?\+=&@!$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2})*)( |\.|\.\.|""|'| ))?

РЕДАКТИРОВАТЬ

Я ошибался в своем местном тесте. Я загружал большую строку, затем добавлял к ней вещи, которые вызывали головокружение .NET Framework, а затем выдавали исключение OOM во время RegEx, а не во время строковых операций (или случайным образом, поэтому игнорируйте предыдущие вещи, которые я сказал).

Это приложение .NET Framework 2.0.

Ответы [ 3 ]

2 голосов
/ 07 апреля 2009

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

Движок Regex должен хранить много информации внутри, и совпадения Greedy могут привести к тому, что Regex выберет большие секции вашей строки 800k, много раз.

Есть хорошая информация об этом за здесь .

1 голос
/ 07 апреля 2009

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

1 голос
/ 07 апреля 2009

Первое, что я бы попробовал, если это возможно для вашего приложения, это разделить входные данные.

Можно ли построчно читать файл (если ввод является файлом), применяя таким образом Регулярное выражение?

Вы должны взглянуть на CLR Profiler . Это может занять некоторое время, чтобы научиться использовать, но оно того стоит. Это поможет вам визуализировать, сколько памяти используют ваши объекты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...