Иногда программы плохо себя ведут.Программисты пишут свои программы, реализуя некоторую логику и затем проверяя, что она работает правильноНо если программист ошибается в логике, могут случиться плохие вещи.
Вероятно, один из самых распространенных способов, с помощью которых программа может ошибиться, - это бесконечный цикл.Возьмите этот пример программы, которая пытается сложить первые n целых чисел:
static int Sum(int n)
{
int sum = 0;
int i = 1;
while (i <= n)
sum += i;
return sum;
}
Что произойдет?Где ошибка?Мы забыли увеличить i
и поэтому оно никогда не превысит n
.Когда вы просто запускаете это, он работает и зависает.Он никогда не остановится сам по себе.
Но если у вас есть бесконечный цикл в программе и вы используете resources в этом цикле, вы можете исчерпать ресурсы.Давайте возьмем другую программу, которая использует рекурсию, чтобы найти сумму:
static int RecursiveSum(int n)
{
return n + RecursiveSum(n - 1);
}
Этот метод также содержит ошибки.У него тоже есть «бесконечный цикл», потому что мы забыли включить условие завершения.Что происходит, когда мы его запускаем?
Процесс прекращается из-за StackOverflowException.
В C # каждый раз, когда вы вызываете метод, вы используете немного ресурса, называемогостек.Стек позволяет программе отслеживать, кто вызвал кто, чтобы при возврате методов возвращаться в нужное место.Аргументы метода и локальные переменные также занимают место в стеке.Когда методы заканчиваются и возвращаются, они освобождают пространство стека, которое они использовали.
Проблема в том, что стек использует память и поэтому он не является бесконечным ресурсом, как время!
Так что естьдва основных способа, которыми программа может создать StackOverflowException
:
- Бесконечный цикл методов, вызывающих методы, вызывающие методы, которые никогда не возвращают
- Серия слишком большого количества уровней рекурсивного вызова, которые в конечном итоге закончится, но стек завершится первым
Первая проблема продемонстрирована вторым способом, описанным выше.Но даже если мы исправим этот метод для добавления условия завершения, в то время как он будет работать для меньших чисел, он в конечном итоге потерпит неудачу, прежде чем произвести сумму для достаточно больших значений n .
Большинство садовых сортовStackOverflowException
относятся к первому типу, но если вы не используете осторожно рекурсию в своих методах, вы можете столкнуться и со второй проблемой.
При отладке StackOverflowException
стек вызовов часто будет выглядетьэто:
...
Program.RecursiveSum(int n = -7770) Line 26 + 0xf bytes C#
Program.RecursiveSum(int n = -7769) Line 26 + 0xf bytes C#
Program.RecursiveSum(int n = -7768) Line 26 + 0xf bytes C#
Program.RecursiveSum(int n = -7767) Line 26 + 0xf bytes C#
Program.RecursiveSum(int n = -7766) Line 26 + 0xf bytes C#
The maximum number of stack frames supported by Visual Studio has been exceeded.
или иногда A
вызывает B
, который вызывает C
, а затем снова вызывает A
и т. д. Вам просто нужно найти цикл, установить точку останова вдиагностируйте, что происходит.