2015-11-15 4 views
3

Я работаю с большим array из struct типов в .NET, который намного больше, чем стандартный 1 МБ, выделенный для стека (за поток). На данный момент я занимаюсь основной темой.Нужно ли явно указывать стек в .NET?

  1. Я прочитал старую статью (возможно, устаревшее), который упоминает явно проклейки стек: http://content.atalasoft.com/h/i/58213648-increasing-the-size-of-your-stack-net-memory-management-part-3

  2. Я заметил, что мои программы часто аварии с stackoverflow exceptions, когда в 32-битном режиме, но не в 64 бит (мой основной режим интереса).

Ориентировочное Гипотезы

  1. Вы должны явно увеличить размер стека, когда вы в 32-битном режиме.

  2. Структура .NET неявно изменяет размер стека для вас в 64-разрядном режиме (хотя это поведение несовместимо с 64-битным режимом).

+2

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

+0

проверить это [ответ] (http://stackoverflow.com/a/20744680/1849444), надеюсь, что это поможет –

ответ

4

Компиляторы C# и VB.NET не имеют способа указать размер исходного стека основного потока. Компилятор C++/CLI делает это. Использование Editbin.exe в post-build event в противном случае является простым обходным решением.

Этот параметр не был выставлен, потому что размер стека по умолчанию очень щедрый для управляемого кода. В отличие от неуправляемых языков, таких как C и C++, нет простого способа потреблять большие суммы стека с объявлениями. Массивы и строки являются ссылочными типами, поэтому они выделяются в куче GC, а не в стеке.

Единственный достойный способ взломать стек - использовать небезопасное ключевое слово stackalloc, которое вы никогда не используете случайно. Или путем рекурсии, либо случайным (безусловно, наиболее распространенным случаем), либо с использованием рекурсивного алгоритма, который хуже, чем O (logN). Такие проблемы сильно опираются на ошибка, Editbin.exe - это всего лишь ленточная помощь, потому что вы все равно будете дуть в стек, когда набор данных достаточно велик.

Только другие примечания, заслуживающие внимания, состоят в том, что начальный размер стека будет 4 МБ вместо 1 МБ, если вы конкретно target x64. Вообще ошибка тоже, вы всегда пользуетесь AnyCPU.


Таким образом, в противном случае слепой совет должен начать поиск этого рекурсивного кода. Он не должен располагаться очень далеко от оператора, создавшего SOE, по крайней мере видимого в трассировке стека. Следите за O (N) хвостом-курсивом, вы не можете рассчитывать на его оптимизацию, определенно не на 32-битный код. Подумайте о замене его или его разбиении на разделы или добавлении проверки на размер набора данных и предварительно исключите исключение.

+0

Я думаю, что стоит остановиться на оптимизации хвостового вызова, что является существенным различием между поведениями x86 и x64 JIT, которые гораздо большее влияние на склонность к выбросу StackOverflowException, чем размер стека потоков. –

Смежные вопросы