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

Wskaźniki -Program przestał działać

VPS Starter Arubacloud
0 głosów
451 wizyt
pytanie zadane 24 lutego 2016 w C i C++ przez Owczarek Niemiecki Obywatel (1,570 p.)

Witam, po raz kolejny "użeram" się tymi lekko mówiąc "głupimi" wskaźnikami w C++.
Już przy lekcji o wskaźnikach z panem Zelentem na yt miałam różne problemy z tym, ale ostatecznie udało mi się zaradzić błędom, przed kasowaniem tablic wyzerowywałam je.Jednak ten sposób teraz nie działa.Program po korzystaniu ze wskaźników przestaje działać.Mam system operacyjny windows 8.1.

Oto kod:

#include <iostream>
#include <time.h>
#include <math.h>
#include <cstdlib>
#include <windows.h>
using namespace std;
clock_t start, stop;
double czas;
long int fib(int n)
{
    if (n==0 || n==1) return 1;
    else return fib(n-1)+fib(n-2);
}
int main()
{
int f;
    cout << "Ile liczb Fibonacciego wyznaczyc?: ";
    cin >> f;
    start=clock();
    cout << fib(f) << endl;
    stop=clock();
    czas=(double) (stop-start)/CLOCKS_PER_SEC;
    cout << "Czas z rekursja wyniosl: " << czas << endl;
    int wyn=0;
    int *fib;
    fib= new int [f];

    fib[0]=1;
    fib[1]=1;
    start=clock();
    for (int i=2; i<=f; i++)
    {
        fib[i]=fib[i-1]+fib[i-2];
        cout << fib[i] << endl;
    }
    stop=clock();
    czas=(double) (stop-start)/CLOCKS_PER_SEC;
    cout << "Czas z interacja wyniosl: " << czas << endl;
    fib=NULL;
    delete [] fib;
    system("pause");
    return 0;
}

Ktoś może pomóc? Bo przez takie coś odechciewa mi się nauki tej wspaniałej rzeczy: programowania.

4 odpowiedzi

+1 głos
odpowiedź 24 lutego 2016 przez criss Mędrzec (172,590 p.)
fib = NULL;
delete [] fib;

Najpierw przestawiasz wskaźnik na 0, a potem próbujesz coś z tamtąd usunąć. Crash murowany.

komentarz 24 lutego 2016 przez Owczarek Niemiecki Obywatel (1,570 p.)
Zawsze to działało, jak nie było tego "Nulla" to właśnie wywalało błąd (program przestał działać), a jak twoim zdaniem to powinno wyglądać?

Zresztą przecież 0 to też liczba i można ją usunąć, prawda? :P
komentarz 24 lutego 2016 przez criss Mędrzec (172,590 p.)

Hah :D Widocznie nie ogarnisz wskaźników :D Nie usuwasz liczby (cokolwiek to znaczy) - usuwasz pamięć z adresu który ma zapisany wskaźnik. 

Działało? Dziwne troche, ale możliwe, nie znam się na tyle na procesach przy samej pamięci. Anyway - nie usuwasz tego co chcesz usunąć. Wskaźnik przetrzymuje adres który potem wysyłasz do delete, a w momencie gdy zmieniasz wartość wskaźnika, delete dostanie coś innego i nawet jeśli się nie wycrashuje to nie usuniesz tego, co byś chciał.

Dobrą praktyką jest ustawianie wskaźnika na null (btw. używaj nullptr - nowsze), ale PO ZWOLNIENIU PAMIĘCI. Inaczej, jak już wyżej opisałem, nie ma to sensu.

+1 głos
odpowiedź 24 lutego 2016 przez draghan VIP (106,230 p.)

Wskaźniki nie są głupie. ;)

Odwołujesz się do elementu poza tablicą, popraw ten fragment:

for (int i=2; i<=f; i++)

Poza tym:

    fib=NULL;
    delete [] fib;

Najpierw powinieneś zwalniać pamięć, a potem przestawiać adres wskaźnika - inaczej próbujesz zwolnić adres NULL, co jest niedobre.

komentarz 24 lutego 2016 przez draghan VIP (106,230 p.)
edycja 24 lutego 2016 przez draghan

Błąd pojawił się dokładnie w momencie wyjścia poza zakres tablicy - wszystkie poprzednie operacje, które odnosiły się do poprawnych adresów Twojej aplikacji wykonały się poprawnie.

Alokacja tablicy o jeden większej naprawia problem, ale powoduje zmarnowanie jednej, ostatniej "szufladki"*. Lepsze jest iterowanie do elementu f-1:

tab = new int[f];
for (int i=2; i < f; i++)

*- jeśli potrzebujesz x elementów, a alokujesz tablicę o rozmiarze x+1 elementów, to jeden element pozostanie nadmiarowy. Akurat w tym przypadku zdarzyło się, że przez przypadek wykorzystanie ostatniego nadmiarowego elementu jest korzystne, bo sprawia że i funkcja rekurencyjna i wersja tablicowa dają jednakowe wyniki

komentarz 24 lutego 2016 przez Owczarek Niemiecki Obywatel (1,570 p.)
Po zrobieniu tak jak mówisz, nie wyświetla ostatniej liczby ciągu.

Przykładowo po wpisaniu, że chcę wyświetlić 5 liczb ciągu, funkcja pokazuje wynik 8, a pętla wywala po kolei: 2, 3, 5
komentarz 24 lutego 2016 przez draghan VIP (106,230 p.)

No i dobrze wyświetla, jeśli zdefiniowałaś (dobrze widziałem, że użyłaś gdzieś żeńskiej odmiany, co nie?) fib[0] = 1 oraz fib[1] = 1, to pięć wyrazów:

fib[0] = 1; // pierwszy element
fib[1] = 1; // drugi element
fib[2] = 2; // trzeci
fib[3] = 3; // czwarty
fib[4] = 5; // piąty

Funkcja rekurencyjna jest tak zdefiniowana, że nie liczy dwóch pierwszych jedynek, a tylko jedną.

komentarz 24 lutego 2016 przez Owczarek Niemiecki Obywatel (1,570 p.)
No rzeczywiście, masz rację :D Ale taką funkcję robił nawet pan Zelent w kursie, czyli pomylił się?
komentarz 24 lutego 2016 przez draghan VIP (106,230 p.)
Czy się pomylił, to nie wiem. Nie oglądałem tego kursu, a żeby ocenić musiałbym obejrzeć, jeśli nie sam odcinek, to przynajmniej kod.

Przepraszam najmocniej, po nicku nijak poznać płci.
0 głosów
odpowiedź 24 lutego 2016 przez mbabane Szeryf (79,280 p.)
nazwa zmiennej taka sama jak nazwa funkcji
komentarz 24 lutego 2016 przez draghan VIP (106,230 p.)
Tutaj nie ma niejednoznaczności, nawet średnio przeszkadza w czytelności, chociaż nie powinno się tak robić. :)
–1 głos
odpowiedź 24 lutego 2016 przez Magicone Nałogowiec (45,100 p.)
fib[0]=1;

fib[1]=1;

 

Błąd leży tutaj, powinieneś odwołać się do wartości, a nie samego wskaźnika.
komentarz 24 lutego 2016 przez draghan VIP (106,230 p.)
Nope. Zapis z użyciem operatora [] odnosi się do wartości, nie do adresu.
komentarz 24 lutego 2016 przez Magicone Nałogowiec (45,100 p.)
A to nie jest tak, że pomijając lukier składniowy dostajemy coś takiego?

(fib + 1), co de facto nie jest równe *(fib + 1)?
komentarz 24 lutego 2016 przez draghan VIP (106,230 p.)
Przetestuj i będziesz wiedział - a nie będziesz musiał ufać jakiemuś random-userowi w internetach. ;)
komentarz 24 lutego 2016 przez criss Mędrzec (172,590 p.)
A jak korzystasz z tablic? :P Do tablicy i do wskaźnika odwoływać się można tak samo. Właściwie to po prostu odwołanie do tablicy jest odwolaniem do wskaźnika.

Podobne pytania

+1 głos
1 odpowiedź 1,423 wizyt
0 głosów
1 odpowiedź 257 wizyt
pytanie zadane 5 grudnia 2016 w C i C++ przez varespol Użytkownik (710 p.)
0 głosów
2 odpowiedzi 1,515 wizyt
pytanie zadane 14 lutego 2016 w C i C++ przez Krst0 Obywatel (1,340 p.)

92,451 zapytań

141,261 odpowiedzi

319,073 komentarzy

61,853 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.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...