Liczby pseudolosowe w c++: problem z pętlą nieskończoną

0

Wróciłem do poznawania c++ po dłuższej przerwie. Nadal jestem początkujący i napotkałem następujący problem. Znalazłem na forum programik do liczb pseudolosowych losujący 30 liczb z przedziału od -10 do 10. Oto on:

#include <iostream>
#include <ctime>
#include <cstdlib>
#include<cstdio>
using namespace std;

int tablica	 [21];
int main()
{
srand(time(NULL));
for (int i = 0; i < 30; i++)
    {
        tablica[i] = (rand() % 20) - 10;
        cout << tablica[i] << " ";
    }
    getchar();
    return 0;
}

Próbowałem go uruchomić w dev c++ i code blocks. Po kompilacji i uruchomieniu wyświetla się pętla nieskończona. Gdy instrukcję int tablica [21]; umieszczam przed funkcją int main (), tak deklaruje się chyba zmienne, tablice globalne program działa bez zarzutu. Gdy pozostawiam ją w funkcji main pojawia się pętla nieskończona. Jak rozwiązać ten problem. Pozdrawiam Krzysztof :)

3

Zapisujesz 30 liczb do 21-elementowej tablicy. Masz UB, w tym przypadku pewnie nadpisujesz odpowiednie adresy na stosie.

self-insert: https://dsp.krzaq.cc/post/180/nie-uzywaj-rand-cxx-ma-random/

1

Za pętlę nieskończoną odpowiedzialny jest getchar(). Trzeba wcisnąć jakiś klawisz, żeby program szedł dalej.

A wielkość tablicy to najlepiej przechowuj w jakiejś stałej, albo użyj prekompilatora. Ważne, żeby tej samej wartości użyć dla warunku końca pętli oraz rozmiaru tablicy.

2

Masz tu nadpisywanie pamięci, które działa tylko w określonych sytuacjach.
Gdy deklarujesz zmienną powyżej main() to jest to zmienna globalna, którą ciężko tak prosto nadpisać inne dane.
Gdy deklarujesz zmienną w środku main() to jest to zmienna lokalna, alokowana na stosie, i można nią wtedy różne fikuśne rzeczy zrobić. Np. zniszczyć licznik pętli, ustawić adres powrotu z funkcji itd. Wszystko zależy od kompilatora, CPU i pewnie paru jeszcze innych rzeczy.

https://pl.wikipedia.org/wiki/Przepe%C5%82nienie_bufora

Edit: Przykład uruchomienia ze zmienną stosową pod CLion/gcc:

#include <iostream>
#include <ctime>
#include <cstdlib>
#include<cstdio>
using namespace std;

int main()
{
    int i;
    int tablica  [21];
    srand(time(NULL));
    for (i = 0; i < 30; i++)
    {
        tablica[i] = (rand() % 20) - 10;
        cout << tablica[i] << " ";
    }
    getchar();
    return 0;
}

Efekt po wciśnięciu Enter:

/home/piotr/CLionProjects/testUB01/cmake-build-debug/testUB01
5 -8 -6 8 -5 -5 -6 9 5 1 -4 2 1 -7 5 9 2 1 -3 -2 6 2 -9 -8 -2 -4 9 -6 3 5 
*** stack smashing detected ***: <unknown> terminated

Process finished with exit code 134 (interrupted by signal 6: SIGABRT)

Co to jest "stack smashing": https://stackoverflow.com/questions/1345670/stack-smashing-detected/50690687

1

Złamałeś zasadę: One Source of Truth - więc płacisz straconym czasem.

    const size_t size=30;
    int tablica[size];
    for(size_t i=0;i<size;++i)

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