Dlaczego mój kod powoduje wyjątek StackOverflowException?

Odpowiedz Nowy wątek
2019-07-06 19:41
0

Mam taki kod:

        int getlosowepytanie()
        {

            rand = new Random();

            number = rand.Next(0, iloscpytan - 1);
            if (uzytePytania[number] == 1)
            {
                return getlosowepytanie();
            }
            else
            {
                return number;
            }
        }

i wywala

System.StackOverflowException: 'Zgłoszono wyjątek typu 'System.StackOverflowException'.'
edytowany 2x, ostatnio: furious programming, 2019-07-06 21:17
jeśli już temat został zakończony zaznacz pomocną odpowiedź - Mondonno 2019-07-07 15:30

Pozostało 580 znaków

2019-07-06 20:07
1
            rand = new Random();

wynieś to z funkcji do klasy.

Pozostało 580 znaków

2019-07-06 20:45
0

Wyjaśnienie: https://docs.microsoft.com/pl[...]=netframework-4.8#Instantiate

Pozostało 580 znaków

2019-07-08 10:45
1

Wyjaśnienie krótkie:

Powinieneś mieć TYLKO JEDEN obiekt klasy Random w CAŁEJ aplikacji. Tzn. musisz go utworzyć TYLKO RAZ. Ty tworzysz go ciągle w swojej metodzie. Powoduje to, że wylosowana liczba zawsze jest taka sama.

Często robi się jakiegoś singletona lub statica, żeby to ogarnąć, np:

public static class RandomHelper
{
    static Random random;

    static RandomHelper()
    {
        random = new Random();
    }

    public int GetRandomInt(int min, int max)
    {
        return random.NextInt....
    }
}

Możesz sobie też zwracać samego random albo możesz z tego zrobić singletona. W zależności od potrzeb.
Dla malkontentów - tak, singleton w tym wypadku jest dobrym rozwiązaniem.

Tak, pod warunkiem, że nie masz testów jednostkowych. i/lub nie używasz kontenera DI. Swoją drogą dziwne, że jeszcze nie zlecieli się przeciwnicy tego zua. - Sarrus 2019-07-08 11:13

Pozostało 580 znaków

2019-07-08 14:59
1
           number = rand.Next(0, iloscpytan - 1);
           if (uzytePytania[number] == 1)
           {
               return getlosowepytanie();
           }

Ja jeszcze dodam, że to jest zły algorytm losowania bez powtórzeń - już dla kilkunastu elementów pod koniec (kiedy większość elementów już była wylosowana) zaczyna działać BARDZO wolno. A tu jeszcze dojdzie przepełnienie stosu.

edytowany 1x, ostatnio: Azarien, 2019-07-08 14:59
dodajmy do tego niepotrzebną rekurencję i obciążenia związane z obsługą stosu ;) - Sarrus 2019-07-08 15:59
no i ta złożoność w pesymistycznym przypadku O(∞) :D /na co zresztą pytający się nadział, gdyby nie ograniczony stos/ - Azarien 2019-07-08 17:10

Pozostało 580 znaków

2019-07-08 16:05
0

Powinieneś kombinować coś w tym kierunku:

var questionsIndexes = new List<int> { 0, 1, 2, 3, 4, 5, 6 };
var listIndex = random.Next(questionsIndexes.Count - 1);
var index = questionsIndexes[listIndex];
questionsIndexes.Remove(index);
edytowany 1x, ostatnio: Sarrus, 2019-07-08 16:05

Pozostało 580 znaków

2019-07-08 17:55
0

Tak na przyszłość . Wklejaj cały kod . Taki błąd wyskakuje wtedy jak funkcja wywołuje samą siebie zbyt dużą liczbę razy.
U mnie taki błąd pojawia się gdy liczba powtórzeń przekroczyła 64547. Zabrakło pamięci na stosie . To jest chyba uzależnione do zasobów komputera.
W takich przypadkach lepiej robić pętle.
Jak funkcja wywołuje następną funkcję to tworzony jest stos wywołań funkcji . Po zakończeniu funkcje są kolejno zdejmowane ze stosu.

edytowany 1x, ostatnio: Zimny Krawiec, 2019-07-08 18:19
Pokaż pozostałe 11 komentarzy
OK. to można zrobić przerwy czasowe w losowaniu liczb ale nadal nie rozumiem jaki to ma związek z przepełnianiem się stosu ? - Zimny Krawiec 2019-07-08 20:04
Przecież @Juhas w swojej odpowiedzi wyjaśnił jaki to ma związek z przepełnieniem stosu. Przeczytaj cały wątek jeszcze raz. - some_ONE 2019-07-08 20:05
Bzdury napisał - Zimny Krawiec 2019-07-08 20:08

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0