Elektroda.pl
Elektroda.pl
X
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

Język C - [c][wskaźniki] Błąd przy uwalnianiu pamięci (usuwaniu wskaźników)

Kryspin92 27 Dec 2012 15:44 2139 20
  • #1
    Kryspin92
    Level 10  
    Mój program służy do tworzenia macierzy i następnie robieniu na nich różnych operacji matematycznych. Na razie tylko dodaje do siebie macierze. W końcu przypomniałem sobie że muszę uwolnić pamięć na końcu programu... Lecz tu nie mam wskaźnika tylko pierw mam tablice wskaźników... więc usuwam wszystko wg schematu:
    Code: c
    Log in, to see the code

    Wszystko działa do momentu kiedy nie wypełnię tablicy dynamicznej danymi
    gdy to zrobię wyskakuję błąd (obrazek)
    cały projekt z MS Visual C++ 2010 dodaje w załączniku
    Język C - [c][wskaźniki] Błąd przy uwalnianiu pamięci (usuwaniu wskaźników)

    Tak już uprzedzam niemiłe komentarze... jest to zadanie na studia ale nie mam pojęcia o co chodzi z tym błędem...
    Attachments:
  • #2
    stanleysts
    Level 27  
    Za dużo miejsca chcesz zaalokować, musisz prawdopodobnie zwiększyć pojemność sterty.
  • #3
    Kryspin92
    Level 10  
    Błąd pokazuje się dopiero w momencie wykonywania funkcji free()
    cała reszta śmiga równo i poprawnie
  • #4
    stanleysts
    Level 27  
    Wogóle to powinieneś chyba zrobić tak:

    Code: c
    Log in, to see the code
  • #5
    Kryspin92
    Level 10  
    Nie wiem, nie ma to większego znaczenia mi się wydaję, bo i typ liczb całkowitych i typ adresowy ma po 4 bajty... przynajmniej tak pokazuje mi mój kompilator.
    sizeof (**pmacierz)
    sizeof (*pmacierz)
    sizeof (int)
    Wszystkie te funkcje zwracają wartość 4, więc przy obliczeniach nie sprawia to większego problemu, bo funkcja malloc() chce tylko konkretną liczbę bajtów.
  • #6
    Krzysztof Gustaw
    Level 23  
    Witam!
    Skoro, jak piszesz na początku, Twój program nie wyrzuca błędu dopóki nie wypełnisz danymi przydzielonych tablic, to błędu musisz szukać w kodzie który zapisuje dane. A tak w ogóle sądzę, że w tym przypadku konieczne jest użycie wskaźników do n-elementowych tablic typu int, a nie wskaźników do elementów typu int, skoro działasz na macierzach a nie na wektorach.
  • #7
    stanleysts
    Level 27  
    Może i zwraca po 4 ale jak sie pisze to tak, żeby było czytelnie i sensownie a nie żeby działało, skąd mam wiedzieć że u ciebie int to 4B a nie np 2...
  • #8
    Kryspin92
    Level 10  
    Mówię przecież że błąd jest dopiero gdy chcę usunąć wskaźniki. Tak to wskaźniki działają bezbłędnie.
  • #9
    krru
    Level 33  
    Bo gdzieś zamazujesz pamięć poza obszarami przydzielonymi - najczęściej tak się zdarza, jak występuje indeksowanie poza przydzielony rozmiar tablicy. Gdy użytkownik przydziela pamięć, pobierane jest jej trochę więcej na informacje organizacyjne (np. rozmiar przydzielonego bloku), poza tym pomiędzy przydzielonymi blokami występują bloki wolne. Podczas zwalniania procedura free czyta te informacje i sprawdza czy coś się nie popsuło. Np. może wyjść, że jeden blok zachodzi na drugi - np. gdy program zamazał informację o wielkości bloku. To jest właśnie taki błąd jak sygnalizowany w tym okienku - heap corrupted.
  • #10
    stanleysts
    Level 27  
    Quote:
    Mówię przecież że błąd jest dopiero gdy chcę usunąć wskaźniki. Tak to wskaźniki działają bezbłędnie.


    No dobrze, ale to źle robiłeś i dlatego to podkreśliłem, to że działa "przypadkowo" dobrze to tylko fart.
    A jeśli nie wykonujesz żadnych operacji między przydzielaniem a zwalnianiem miejsca to się też wysypuje?
  • #11
    Kryspin92
    Level 10  
    Właśnie nie występuje żaden błąd i to mnie dziwi
  • #12
    stanleysts
    Level 27  
    No bo jest tak jak Ci kolega wyżej pisał.
  • #13
    Kryspin92
    Level 10  
    stanleysts wrote:
    Wogóle to powinieneś chyba zrobić tak:

    Code: c
    Log in, to see the code



    Zrobiłem tak jak mówiłeś i teraz tworząc mniejszy program aby było mniej do analizowania wyskakuje ten sam błąd:
    main.cpp:
    Code: c
    Log in, to see the code

    wszystkie funkcje normalnie są w różnych plikach ale na forum zrobiłem to w jednym pliku...
    zawartość pliku o nazwie "jeden.mat"(w programie należy napisać nazwę bez rozszerzenia):
    
    3 3
    1
    2
    3
    /kw/
    4
    3
    2
    /kw/
    1
    2
    3
    /kw/
    
    


    Czy możecie mi powiedzieć w którym miejscu źle myślę ?
  • #14
    stanleysts
    Level 27  
    To jest źle napewno:

    bool dodroz(char nazwa[], char roz[3])

    Jak mu podajesz tablice też jako drugi argument to ma być:
    bool dodroz(char nazwa[], char roz[])
  • #15
    Kryspin92
    Level 10  
    stanleysts wrote:
    To jest źle napewno:

    bool dodroz(char nazwa[], char roz[3])

    Jak mu podajesz tablice też jako drugi argument to ma być:
    bool dodroz(char nazwa[], char roz[])


    Zgadzam się ale w sumie to działało (wpisałem 3 bo chciałem ograniczyć jakoś wielkość tablicy ale to niepotrzebnie) ale nadal nie rozwiązuje to mojego problemu.
    wskaźnik **pmacierz wypełniony danymi nadal nie daje się usunąć z pamięci i jest błąd
  • #16
    beluosus
    Level 25  
    stanleysts wrote:
    To jest źle napewno:

    bool dodroz(char nazwa[], char roz[3])

    Jak mu podajesz tablice też jako drugi argument to ma być:
    bool dodroz(char nazwa[], char roz[])
    na pewno*

    Śmieszne rzeczy. :) Rozmiar tablicy ma znaczenie dopiero przy drugim i dalszych wymiarach (potrzebne to jest do obliczenia pozycji w pamięci).

    Co do problemu to tak pobieżnie patrząc problem leży tutaj:
    Code: c
    Log in, to see the code

    Powinien być <, a nie <=, wtedy piszesz poza mat. Btw nie musisz podawać referencji, żadnej oszczędności tu nie będzie (tak czy siak przekażesz tę samą ilość bajtów przez argument), a adresu wskaźnika nie zmieniasz.
  • #17
    Kryspin92
    Level 10  
    beluosus wrote:

    Co do problemu to tak pobieżnie patrząc problem leży tutaj:
    Code: c
    Log in, to see the code

    Powinien być <, a nie <=, wtedy piszesz poza mat. Btw nie musisz podawać referencji, żadnej oszczędności tu nie będzie (tak czy siak przekażesz tę samą ilość bajtów przez argument), a adresu wskaźnika nie zmieniasz.


    Code: c
    Log in, to see the code


    ta pętla nie powoduje że mat zajmuje więcej miejsca bo j = 3 (przy s = 3) jest tylko do sprawdzenia czy aby na pewno jest to koniec wiersza... (mógłby taki błąd wystąpić przy błędnym pliku to prawda ale to nic nie zmienia)
  • Helpful post
    #18
    beluosus
    Level 25  
    Ah, nie powiedziałeś co jest zawartością pliku, jak rozumiem na końcu każdego wiersza jest "/kw/". Ale błąd jest nadal, bo porównujesz adresy, a nie tekst. Spróbuj:
    Code: c
    Log in, to see the code
  • #19
    Kryspin92
    Level 10  
    beluosus wrote:
    Ah, nie powiedziałeś co jest zawartością pliku, jak rozumiem na końcu każdego wiersza jest "/kw/". Ale błąd jest nadal, bo porównujesz adresy, a nie tekst. Spróbuj:
    Code: c
    Log in, to see the code


    Pomogło nie mogę uwierzyć ha ha od 2 tygodni się zastanawiałem o co tu chodzi... a więc
    Code: c
    Log in, to see the code

    zawsze zwracała fałsz ?
  • Helpful post
    #20
    beluosus
    Level 25  
    Krótko mówiąc, tak. :)
  • #21
    Kryspin92
    Level 10  
    Dzięki ci bardzo :) ha ha moje zaliczenie jest uratowane :)