Что такое исключение StackOverFlow в vb.net? - PullRequest
3 голосов
/ 20 сентября 2009

Я даже не знаю, что вызвало это в моем приложении. Что это? Я создал новый экземпляр класса (класс находился в другом файле), но при первом вызове метода он вызывает исключение StackOverFlow.

Единственное, что, по-моему, логично выкинет исключение переполнения стека, - это если кто-то отвергнет Джона Скита.

А если серьезно, что это? Я справился с этим, создав другой класс в том же файле, что и первый класс, и использовал его для вызова методов для меня.

Ответы [ 9 ]

6 голосов
/ 20 сентября 2009

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

Вот тривиальный пример глючной рекурсии (без конкретного PL).

function int length(list l) {
    if (empty(l)) {
        return 0;
    } else {
        return 1 + length(l);  // should be 'return 1 + length(tail(l));
    }
}

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

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

4 голосов
/ 20 сентября 2009

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

void MyMethod()
{
    MyMethod();
}

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

P.S. SO был назван в честь конкретного исключения (это принципиально и не ограничивается .NET), это просто умное имя для сайта разработчика.

2 голосов
/ 20 сентября 2009

В стеке хранится список функций, которые в данный момент вызываются, а также используемые переменные и параметры. Поэтому, если функция Main вызывает функцию A, а затем функцию A вызывает функцию B, и они используют переменные c, d и e, стек будет содержать всю эту информацию. Тем не менее, стек только такой большой. Поэтому, если функция B затем вызывает функцию C, которая вызывает функцию D ... и т. Д., Заканчивая сотнями вложенных функций, в конце концов, стек будет «переполнен» - недостаточно места для хранения другого вызова функции.

Как уже отмечали другие люди, это обычно происходит с рекурсивной функцией (где функция B вызывает функцию B, которая затем вызывает функцию B ...) - в конце концов, стек переполнится. Вам нужно будет найти, где вызывается эта рекурсивная функция и почему она не выходит из рекурсивного цикла, когда она должна.

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

2 голосов
/ 20 сентября 2009

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

2 голосов
/ 20 сентября 2009

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

1 голос
/ 20 сентября 2009

Это обычно вызывается рекурсивным вызовом функции, когда этот рекурсивный вызов никогда не завершается. Вы можете получить это несколькими способами. Одним из способов может быть рекурсивный алгоритм без базового случая, другим распространенным является создание объектов A и B, которые создают друг друга в своих конструкторах и т. Д.

Рекомендую пройтись по отладчику и выяснить:)

0 голосов
/ 01 июля 2017

У меня была ошибка Stackoverflow. Я использовал подпрограмму, которая добавила 1 к счетчику, а затем снова вызвала ту же самую подпрограмму. Примерно через каждые 2500-3000 циклов я получал ошибку переполнения стека. Я добавил цикл DO ..., который вызывает процедуру, я использую VB Express:

ДО:

Public Sub mainloop()

Dim cntr as integer

If cntr >= 5000  ( I just picked a number at random)

    me.close  ( I close the program)

...               (This is where I would manipulate the cntr for diff 
results)

cntr = cntr + 1  ( increment the cntr)

mainloop()        (re call my loop) 

End IF

End Sub

(как я уже говорил, примерно через 2500-3000 я получу ошибку Stackoverflow)

ПОСЛЕ: (Поместите это для выполнения первым)

Dim LoopCntr as integer

Do While LoopCntr <= 40000  (this my number.. Use your own number)

If LoopCntr > 40000 Then

        Exit Do
End If

mainloop()       (The mainloop() has not been changed just the method of calling it)
LoopCntr = LoopCntr + 1

Loop

me.close        (When LoopCntr reaches max it closes the program)

(После добавления Do..Loop моя программа работала 40000 раз без «Stackoverflow»)

0 голосов
/ 25 декабря 2014

У меня возникла эта проблема, я заметил, что неправильно набрал lstEncounter. Как я узнал в своем классе C ++, проблема заключается в рекурсивном алгоритме, который в основном вызывает себя с теми же параметрами. Мой пример, где я получил ошибку:

Property Encounter(ByVal N As Integer)
    Get
        If N < lstEncounters.Count Then
            Return Encounter(N)
        Else
            Return Nothing
        End If
    End Get
    Set(value)
        lstEncounters(N) = value
    End Set
End Property
0 голосов
/ 26 июня 2014

Я недавно портировал старое приложение VB6 на VB.NET, которое использовало чудовищную рекурсивную функцию для сортировки столь же большого количества данных. Алгоритм был в порядке, но выполнение постоянно вызывало ошибку переполнения стека. После долгих раздумий я понял, что VB творит много магии в коде: простое приведение типов имеет свою цену. Таким образом, рекурсивная функция слишком сильно полагалась на позднюю привязку вместо использования переменных типа, что приводило к ОГРОМНОМУ количеству приведения, синтаксического анализа и т. Д. (Одна строка кода могла вызывать от 2 до 10 функций ...), что очевидно, сделал переполнение стека.

TL; DR: используйте DirectCast () и статическое связывание (типизированные переменные), чтобы предотвратить переполнение VB стека во время выполнения в рекурсивной функции.

...