Пожалуйста, определите исключение переполнения стека - c # - PullRequest
0 голосов
/ 17 июля 2011

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

Ответы [ 3 ]

7 голосов
/ 17 июля 2011

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

Вероятно, один из самых распространенных способов, с помощью которых программа может ошибиться, - это бесконечный цикл.Возьмите этот пример программы, которая пытается сложить первые 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:

  1. Бесконечный цикл методов, вызывающих методы, вызывающие методы, которые никогда не возвращают
  2. Серия слишком большого количества уровней рекурсивного вызова, которые в конечном итоге закончится, но стек завершится первым

Первая проблема продемонстрирована вторым способом, описанным выше.Но даже если мы исправим этот метод для добавления условия завершения, в то время как он будет работать для меньших чисел, он в конечном итоге потерпит неудачу, прежде чем произвести сумму для достаточно больших значений 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 и т. д. Вам просто нужно найти цикл, установить точку останова вдиагностируйте, что происходит.

6 голосов
/ 17 июля 2011

A переполнение стека происходит, когда у вас слишком много методов, вызывающих друг друга.

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

Переполнение стека происходит при заполнении этого стека.

1 голос
/ 17 июля 2011

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

...