• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Dlaczego program nie jest ubijany przy próbie zapisania danych w nieprzyznanej przestrzeni adresowej?

0 głosów
431 wizyt
pytanie zadane 4 maja 2015 w C i C++ przez zamkot Nowicjusz (190 p.)

Cześć, Napisałem taki kod generujący n liczb Fibonacciego, ale nie rozumiem czegoś odnośnie jego działania. Na początku zdefiniowana jest tablica 20-elementowa, więc spodziewam się, że jeżeli poproszę program o wygenerowanie np. 30 liczb to zostanie on zabity przez system, ale tak się nie dzieje. Zamiast tego, program poprawnie podaje dokładnie 21 wyrazów ciągu. Taki sam efekt uzyskuję niezależnie od tego jak dużą liczbę wprowadzę. Dlaczego program nie jest ubijany? Dlaczego może podać o jedną wartość więcej niż przewiduje ilość komórek w tablicy, ale więcej już nie?

#include <iostream>

using namespace std;

long double fib[20];
int n;

int main()
{
    cout << "Ile liczb podac?" << endl;
    cin >> n;

    fib[0]=1; fib[1]=1;

    for(int i=0; ((i<=1)&&(i<=n-1)); i++)
    {
       cout <<"wyraz nr "<<i+1<<": "<<fib[i]<<endl;
    }

    for(int i=2; i<=n-1; i++)
    {
        fib[i]=fib[i-1]+fib[i-2];
        cout <<"wyraz nr "<<i+1<<": "<<fib[i]<<endl;
    }

    return 0;
}

4 odpowiedzi

+1 głos
odpowiedź 4 maja 2015 przez hit02 Nałogowiec (33,970 p.)
edycja 4 maja 2015 przez hit02
 
Najlepsza
Program wypisuje 21 liczb, ponieważ zmienną n deklarujesz za tablicą, więc wyjeżdżając za tablicę nadpisujesz n zerem. Jeśli chcesz się dowiedzieć, czemu zerem, to poczytaj o IEEE754, oraz o little endian.

Jeśli zadeklarujesz n przed tablicą, to program wypisze więcej liczb, a przy zapisie dostatecznie daleko zostanie zabity.

@edit Pomyliłem się. Poczytaj o little endian a nie o big endian.
komentarz 4 maja 2015 przez zamkot Nowicjusz (190 p.)
Dokładnie tego chciałem się dowiedzieć. Wielkie dzięki
komentarz 4 maja 2015 przez hit02 Nałogowiec (33,970 p.)
Cieszę się, że pomogłem. :)
+1 głos
odpowiedź 4 maja 2015 przez RemigiuszWaleska Obywatel (1,170 p.)

Co do pytania dlaczego generuje 21 wyrazów ciągu odpowiedział poprawnie Kaspersky.

Ale zastanawiam się czy trochę nie przekombinowałeś w kodzie.

Po co ci pierwsza pętla? Gdybyś ją usunął a po "cin >> n;" przeniósł "long double fib[n];".

To kod byłby chyba bardziej przejrzysty, działał by na określoną przez użytkownika liczbe elementów ciągu.

0 głosów
odpowiedź 4 maja 2015 przez Kapersky Obywatel (1,060 p.)
i<=n-1 chyba to powinieneś zmienić na i< n-1, ale teraz kończę pracę i tak na szybko pisze. Bede w domu to zobaczę.
komentarz 4 maja 2015 przez zamkot Nowicjusz (190 p.)
edycja 4 maja 2015 przez zamkot
Dzięki za odpowiedź ;)

Słaba nierówność jest tam potrzebna. Zauważ, że bez niej program nie radzi sobie kiedy n=1 lub n=2.
Chyba, że mowisz o warunku w drugiej pętli - tam też musi być i<=n-1, bo program wypisywałby o jeden wynik mniej niż chcemy.

Zaznaczam że program działa poprawnia, a 'problem' polega na tym że nie da się go wysypać w sposób jakiego się spodziewam. (Zająłem się c++ ledwie tydzień temu. Nie mam też doświadczenia z innymi językami, nie licząc znajomości podstaw NI LabVIEW)
komentarz 4 maja 2015 przez Kapersky Obywatel (1,060 p.)
Poza tym czemu działasz na double jak mogą być int ?
komentarz 4 maja 2015 przez zamkot Nowicjusz (190 p.)
W tym konkretnym przypadku rzeczywiście int by wystarczyły ,ale gdyby ktoś uparł się żeby generować więcej niż te 20 wyrazów to int wysiada juz przy czterdziestej siodmej liczbie Fibonacciego bo nie mieści dużych liczb i podaje bzdury.
0 głosów
odpowiedź 4 maja 2015 przez zamkot Nowicjusz (190 p.)

Rzeczywiście, propozycja RemigiuszWaleska sprawia że kod jest zarówno bardziej użyteczny jak i przejrzysty. Dziękuję Ci za nią, bo niewątpliwie przyda mi się to w przyszłości, jednak nie o to chodziło mi gdy zadawałem pytanie. Chcę znaleźć wyjaśnienie zjawiska które zaobserwowałem, żeby lepiej zrozumieć środowisko i działanie systemu operacyjnego.

Wróćmy do pierwotnego kodu. Zaznaczę raz jeszcze:
-Z założenia miał być w stanie wygenerować maksymalnie 20 liczb - tak chciałem;
-Robi to poprawinie dla wszystkich wartości n z przedziału <0, 20>, czyli jeżeli zada się liczbe 7 - generuje 7 wyrazów, analogicznie dla 0, 5, 12, 20 i każdej innej z przedziału. Nie ma więc problemu z rodzajem nierówności o której mówicie, o czym można się przekonać uruchamiając kod. (przypominam że wyraz nr 1 ma w tabeli index 0 i tak dalej)
W swoim tutorialu pan Mirosław mówił, że przy próbie odwołania się do przestrzeni adresowej nam nie przypisanej to program jest ubijany przez planistę systemu. 
Np. Jeżeli wpiszemy wartość n większą od 20 to może to zajsć w linijce:
 

fib[i]=fib[i-1]+fib[i-2];


przy i=20.
Pan MIrosław zaznacza też że jeżeli dana przetrzeń adresowa nie jest obecnie zajęta, to system może nam ją przydzielić i program powinien zadziałać - widocznie tak się dzieje przy i=20 kiedy chcemy wpisać do tabeli wartość o indexie 20, a więc dwudziestą pierwszą z kolei! 
Jednak w kolejnych iteracjach nie dzieje się ani jedno ani drugie - program nie zawiesza się, ale też nie wypisuje kolejnych wyrazów.



 

Podobne pytania

0 głosów
0 odpowiedzi 560 wizyt
pytanie zadane 24 lipca 2018 w C i C++ przez GallAnonim Nowicjusz (120 p.)
+1 głos
2 odpowiedzi 327 wizyt
pytanie zadane 4 lipca 2016 w C i C++ przez Gracjan Pasik Obywatel (1,810 p.)
0 głosów
1 odpowiedź 354 wizyt

93,753 zapytań

142,713 odpowiedzi

323,356 komentarzy

63,348 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Twierdza Linux. Bezpieczeństwo dla dociekliwych

Aby uzyskać rabat -10%, użyjcie kodu pasja-linux, wpisując go w specjalne pole w koszyku.

...