Foreversoft.ru

IT Справочник
0 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Stack overflow ошибка

Ошибка “Stack overflow” — что это и как ее избежать?

Можете объяснить, когда возникает эта ошибка и как от нее избавиться?

2 ответа 2

Это означает, что в стеке недостаточно места.

Причины — например, слишком глубокая рекурсия (редко), или слишком большие локальные переменные (куда чаще), или и то и другое сразу 🙂

Как избавиться? Опять же, можно просто в настройках компилятора поднять размер стека.

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

практически гарантированно даст переполнение стека. В отличие от

Словом, смотрите, кто съедает много стековой памяти, и избавляйтесь от него.

Про стек и другие типы данных:

  • Стековые данные. На них память выделяется при заходе в процедуру и освобождается при её завершении. Максимальный размер стека программы составляет 1 GB и для 32-битных, и для 64-битных приложений. (Размерстека задаётся линковщиком и по умолчанию составляет 1 MB)
  • Статические данные. Ограничение накладывается на размер самого исходного кода программы и размер статически выделяемой памяти. В языке C++ такие данные обычно представлены переменными, объявленными на глобальном уровне вне процедур. Как для 32-битных, так и для 64-битных программ, ограничение на размер статически выделяемой памяти равно 2 GB.
  • Динамические данные. Это данные, память на которые динамически выделяется во время исполнения программы. В C++ такое выделение обычно осуществляется функцией malloc или оператором new. В 32-битных программах размер динамически выделяемой памяти ограничен 2 GB, в 64-битных — 8 TB.

У 32-битного приложения запущенного в 32-битной Windows суммарный размер всех перечисленных типов данных не должен превышать 2 GB. (Практически ограничение равно 1.75GB из-за требований к памяти самой операционной системы) 32-битная программа, собранная с ключом /LARGEADDRESSAWARE:YES может выделять до 3-х гигабайт памяти, если 32-битная операционная система Windows запущена с ключом /3gb. Эта же 32-битная программа, запущенная на 64-битной системе, может выделить почти 4 GB памяти (на практике около 3.5 GB).

Ограничения на максимальный размер статически-выделяемой и стековой памяти одинаковы для 32-х и 64-х битных Windows приложений. Это связано с форматом типа файлов Portable Executable (PE), который используется в Windows для описания exe и dll файлов. Статические и стековые данные располагаются в первых 2-х GB адресного пространства приложения. Стоит помнить, что данные ограничения накладываются самой операционной системой и не зависят от используемого компилятора.

  1. Как написал коллега [Harry] в ответе.

Это означает, что в стеке недостаточно места.

Что такое StackOverflowError?

355 Ziggy [2008-10-18 11:13:00]

Что такое StackOverflowError , что его вызывает, и как мне с ними бороться?

java exception-handling stack-overflow

Читать еще:  Файл журнала ошибок

13 ответов

331 Решение Sean [2008-10-18 11:34:00]

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

У вашего процесса также есть куча, которая живет в нижней части вашего процесса. Когда вы выделяете память, эта куча может расти в верхнем конце вашего адресного пространства. Как вы можете видеть, существует вероятность того, что куча «столкнется» со стеклом (немного как тектонические пластины . ).

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

Однако при программировании графического интерфейса возможно генерировать непрямую рекурсию. Например, ваше приложение может обрабатывать сообщения с краской, а при их обработке оно может вызывать функцию, которая заставляет систему отправлять другое сообщение с краской. Здесь вы явно не называли себя, но OS/VM сделала это для вас.

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

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

74 Varun [2015-03-26 16:06:00]

Чтобы описать это, сначала давайте понять, как хранятся локальные переменные и объекты.

Локальная переменная хранится в стеке:

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

Когда вызов функции вызывается Java-приложением, стек стека выделяется в стеке вызовов. Фрейм стека содержит параметры вызываемого метода, его локальные параметры и обратный адрес метода. Адрес возврата обозначает точку выполнения, из которой выполнение программы должно продолжаться после возврата вызванного метода. Если нет места для нового стека кадров, StackOverflowError вызывается виртуальной машиной Java (JVM).

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

Пример, показывающий StackOverflowError , показан ниже:

StackOverflowErrorExample.java:

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

Читать еще:  Как исправить ошибки в тексте ворд

Пример выполнения примера с использованием флага -Xss1M который определяет размер стека потоков равным 1 МБ, показан ниже:

В зависимости от начальной конфигурации JVM результаты могут отличаться, но в конечном итоге следует вызывать StackOverflowError . Этот пример — очень хороший пример того, как рекурсия может вызывать проблемы, если их не применять с осторожностью.

Как бороться с StackOverflowError

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

Если вы подтвердили правильность реализации рекурсии, вы можете увеличить размер стеков, чтобы разрешить большее количество вызовов. В зависимости от установленной виртуальной машины Java (JVM) размер стека по умолчанию может равняться либо 512 КБ, либо 1 МБ. Вы можете увеличить размер стека потоков, используя флаг -Xss . Этот флаг может быть указан либо через конфигурацию проектов, либо через командную строку. Формат аргумента -Xss : -Xss [g|G|m|M|k|K]

61 Khoth [2008-10-18 11:31:00]

Если у вас есть такая функция, как:

Затем foo() будет продолжать называть себя, все глубже и глубже, и когда пространство, используемое для отслеживания того, какие функции вы заполнены, вы получаете ошибку.

23 Cheery [2008-10-18 13:06:00]

Переполнение стека означает, что: переполнение стека. Обычно в программе есть один стек, содержащий переменные и адреса локальной области, в которые нужно вернуться, когда выполнение процедуры заканчивается. Этот стек имеет тенденцию быть фиксированным диапазоном памяти где-то в памяти, поэтому он ограничивает, сколько он может содержать значения.

Если стек пуст, вы не можете постить его, если вы получите ошибку стека стека.

Если стек заполнен, вы не можете нажать, если вы получите ошибку.

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

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

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

Самая простая вещь, которую вы могли бы попробовать, это увеличить размер стека, если сможете. Если вы не можете этого сделать, вторая лучшая вещь — посмотреть, есть ли что-то, что явно вызывает переполнение стека. Попробуйте, напечатав что-то до и после вызова в рутину. Это поможет вам узнать провалившуюся процедуру.

Читать еще:  Ворд не выделяет ошибки красным

8 Greg [2008-10-18 11:19:00]

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

Как вы говорите, вам нужно показать код.: -)

Ошибка обычно происходит, когда ваша функция вызывает слишком много гнезд. См. Поток Qaru Code Golf для некоторых примеров того, как это происходит (хотя в случае этого вопроса ответы намеренно вызывают переполнение стека).

5 Vikram [2012-07-18 00:23:00]

StackOverflowError относится к стеку, поскольку OutOfMemoryError относится к куче.

Неограниченные рекурсивные вызовы приводят к тому, что пространство стека израсходовано.

В следующем примере StackOverflowError :

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

4 splattne [2008-10-18 11:43:00]

Наиболее распространенной причиной является чрезмерно глубокая или бесконечная рекурсия. Если это ваша проблема, этот учебник о Java Recursion может помочь понять проблему.

3 Yiling [2013-01-16 22:49:00]

Вот пример рекурсивного алгоритма для обращения к односвязному списку. На ноутбуке со следующей спецификацией (память 4G, процессор Intel Core i5 2.3GHz, 64-разрядная версия Windows 7) эта функция будет запущена с ошибкой StackOverflow для связанного списка размером около 10 000.

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

Итеративная версия того же алгоритма:

3 Rahul Sah [2017-03-30 14:08:00]

StackOverflowError — это ошибка времени выполнения в java.

Он вызывается, когда объем памяти стека вызовов распределяется с помощью JVM.

Обычный случай aa StackOverflowError который бросается, когда стек вызовов превышает из-за чрезмерной глубокой или бесконечной рекурсии.

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

0 Sergiu [2014-01-25 17:01:00]

Термин «переполнение стека» (переполнение) часто используется, но является неправильным; атаки не переполняют стек, а буферы в стеке.

0 John S. [2016-02-12 02:02:00]

A StackOverflowError в основном заключается в том, что вы пытаетесь сделать что-то, что, скорее всего, называет себя и продолжается бесконечно (или пока оно не даст StackOverflowError).

add5(a) будет вызывать себя, а затем снова называть себя и т.д.

Ссылка на основную публикацию
Adblock
detector