2013-03-18 3 views
5

У меня есть приложение C# WinForm, которое я запускаю с режимом x86. Он отлично работает с режимом x86. проблема возникает, когда я запускаю это приложение в любом режиме процессора. Я получаю ниже упомянутой ошибки:StackOverflowException даже после увеличения размера стека

An unhandled exception of type 'System.StackOverflowException' occurred in XXXXXX.dll

Я знаю, что это может быть вызвано бесконечными петлями, а что нет, но та же ошибка должна происходить в режиме x86 в этом случае. Я знаю, что это происходит не из-за бесконечных итераций. Это как-то связано с переполнением стека.

После выполнения некоторых исследований я увеличил размер стека с Editbin

из

Editbin.exe /Stack:14000000 "$(TargetDir)MyProject.exe"

в

Editbin.exe /Stack:14000000 "$(TargetDir)MyProject.exe"

Любая идея, что может быть причиной и какие направления я должен идти к ?

+1

Является 'XXXXXX.dll' вашей dll или ссылкой? – Guvante

+2

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

+0

Как выглядит трассировка стека исключений? – AaronLS

ответ

7

Причина - бесконечная рекурсия. Приложите отладчик и посмотрите на трассировку стека при возникновении исключения.

+0

Затем он также выйдет из строя в режиме x86. – Guffa

+0

@ Guffa: Это * гарантировано * для этого? Может ли джиттер, например, решить сделать рекурсивную оптимизацию хвоста в одном случае, а не в другом? –

+0

@EricLippert: Тогда он просто закроется вместо сбоев. – Guffa

35

My bathtub is overflowing.

Попытайтесь получить большую ванну.

OK, I did that. My bathtub is still overflowing.

Попробуйте получить еще большую ванну.

OK, it's still overflowing! I have a huge bathtub but it is still overflowing!


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

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

I know this could be because of infinite loops and what not but the same error should occur in the x86 mode in that case.

Это утверждение неверно. Нет требования, чтобы произошла одна и та же ошибка.

Why is it different depending on whether or not I'm targetting a particular cpu?

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

Suppose for the sake of argument that there is no unbounded recursion.

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

В этом случае сделать стек больше - плохая идея. Вместо этого найдите глубоко рекурсивный алгоритм и превратите его в итерационный алгоритм.

+0

Сменив глубоко рекурсивный алгоритм на итеративный алгоритм с явным стеком по этой точной причине, могу только сказать, что это действительно сочное решение. Рекурсия - естественный способ структурирования некоторых алгоритмов, и читаемость этого конкретного алгоритма полностью уничтожена (не говоря уже о том, что она стала медленнее). Я предпочел бы, чтобы стек мог быть «растягивающимся», как обычные распределения, которые в основном неограничены. –

+0

@romkyns: Я согласен, что итеративное решение часто намного менее изящно. Что делать, если вы использовали «ожидание», чтобы заставить компилятор выполнить эту работу за вас? –

2

Можете ли вы просмотреть трассировку стека?

Вы можете прочитать эту собственность: Environment.StackTrace.

Если функция stacktrace выполнила заданный порог, вы можете вернуть функцию. Вы также можете попробовать заменить некоторые рекурсивные функции на циклы. (Объект StackOverflowException не может быть захвачен блоком try-catch, если .net 2.0 и выше)

3

Причина, по которой вы получаете переполнение стека, просто потому, что вы используете слишком много стека.

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

Решение состоит в том, чтобы выяснить, что именно в вашей программе использует столько пространства стека. Вы должны искать такие вещи, как рекурсивные функции, которые запускают слишком много уровней. Хорошо реализованная рекурсивная функция будет использовать что-то вроде 10 или 100 уровней рекурсии, но если вы используете неправильную рекурсию, возможно, вы можете иметь 10000000 уровней рекурсии, которые будут использовать много пространства стека.