• 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ć

Aruba Cloud PRO i VPS, Openstack, VMWare, MS Hyper-V
0 głosów
305 wizyt
pytanie zadane 24 lutego 2016 w C i C++ przez Owczarek Niemiecki Obywatel (1,560 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,640 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,560 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,640 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,020 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,020 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,560 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,020 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,560 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,020 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,260 p.)
nazwa zmiennej taka sama jak nazwa funkcji
komentarz 24 lutego 2016 przez draghan VIP (106,020 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,480 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,020 p.)
Nope. Zapis z użyciem operatora [] odnosi się do wartości, nie do adresu.
komentarz 24 lutego 2016 przez Magicone Nałogowiec (45,480 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,020 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,640 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,307 wizyt
0 głosów
1 odpowiedź 210 wizyt
pytanie zadane 5 grudnia 2016 w C i C++ przez varespol Użytkownik (710 p.)
0 głosów
2 odpowiedzi 1,292 wizyt
pytanie zadane 14 lutego 2016 w C i C++ przez Krst0 Obywatel (1,340 p.)

89,768 zapytań

138,374 odpowiedzi

309,456 komentarzy

59,679 pasjonatów

Advent of Code 2022

Top 15 użytkowników

  1. 1074p. - Argeento
  2. 1010p. - rucin93
  3. 1006p. - Michal Drewniak
  4. 1000p. - Łukasz Eckert
  5. 974p. - TheLukaszNs
  6. 949p. - JMazurkiewicz
  7. 946p. - adrian17
  8. 933p. - Jarosław Roszyk
  9. 889p. - nidomika
  10. 860p. - Mikbac
  11. 847p. - ssynowiec
  12. 799p. - Hubert Chęciński
  13. 772p. - Mawrok
  14. 768p. - overcq
  15. 764p. - Vinox
Szczegóły i pełne wyniki

Motyw:

Akcja Pajacyk

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

Sklep oferujący ćwiczenia JavaScript, PHP, rozmowy rekrutacyjne dla programistów i inne materiały

Oto dwie polecane książki warte uwagi. Pełną listę znajdziesz tutaj.

...