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

Dynamiczna alokacja pamięci

Object Storage Arubacloud
0 głosów
292 wizyt
pytanie zadane 7 kwietnia 2023 w C i C++ przez Zuzan Początkujący (390 p.)

Witam, mam do napisania taką funkcję:

struct matrix_t* matrix_create_struct(int width, int height);

Funkcja alokuje pamięć na strukturę typu matrix_t, a następnie na macierz o wymiarach width x height oraz ustawia odpowiednie wartości w pozostałych polach struktury - inicjuje strukturę matrix_t*.

Funkcja zwraca wartość NULL w przypadku kiedy nie udało się poprawnie utworzyć struktury lub wskaźnik do nowo utworzonej struktury.

W przyadku porażki cała zaalokowana pamięć powinna zostać zwolniona.

Funkcja napisana przeze mnie wygląda następująco:

struct matrix_t* matrix_create_struct(int width, int height){
    if(width<=0||height<=0) return NULL;
    struct matrix_t* m = (struct matrix_t*) malloc(sizeof(struct matrix_t));
    if(m == NULL)
        return NULL;
    int i, j;
    m->height=height;
    m->width=width;
    (m->ptr) = (int**) malloc(height * sizeof(int*));
    if ((m->ptr) == NULL) {
        free(m);
        return NULL;
    }

    for (i = 0; i < height; i++) {
        *((m->ptr)+i) = (int*) malloc(width * sizeof(int));
        if (*((m->ptr)+i) == NULL) {
            for (j =0; j<i; j++) {
                free(*((m->ptr)+j));
            }
            free((m->ptr));
            free(m);
            return NULL;
        }
    }

    return m;
}

W testach wyskakuje mi błąd o takiej treści:

Próba zwolnienia niezaalokowanego wcześniej bloku pamięci (nieznany wskaźnik)

Nie do końca wiem, w którym momencie popełniam błąd i z czego to wynika. Byłabym wdzięczna za pomoc. Z góry dziękuję.

komentarz 7 kwietnia 2023 przez j23 Mędrzec (194,920 p.)

A dlaczego zakładasz, że tej funkcji jest błąd? Ja go w niej nie widzę.

Dlaczego tak: *((m->ptr)+i), a nie po ludzku m->ptr[i]?

komentarz 7 kwietnia 2023 przez Zuzan Początkujący (390 p.)
edycja 8 kwietnia 2023 przez Zuzan

Nie mogę korzystać z operatora [] w tym zadaniu. Błąd pojawia się w testach i wygląda tak: 

Sprawdzanie poprawności działania funkcji matrix_create_struct⏎
#####START##########END##########START#####Analiza zasobów: PORAŻKA Próba zwolnienia niezaalokowanego wcześniej bloku pamięci (nieznany wskaźnik)</strong>⏎
9 9 2 -1 7 -8 ⏎
2 4 -7 -9 2 -1 ⏎
-1 2 6 4 6 -10 ⏎
0 7 -4 -2 1 -7 ⏎
-1 -2 5 3 -10 4 ⏎
3 -4 6 -8 -9 -4 ⏎
6 10 -8 7 2 -1 ⏎
-8 -6 -7 7 2 9 ⏎
9 -4 3 3 8 -7 ⏎
9 -7 -8 0 -4 8 ⏎
5 4 8 6 -4 10 ⏎
1 9 -3 -6 8 -3 ⏎
-5 1 -3 3 10 0 ⏎

Program przerwany; kod błędu=140 (Sygnał SIGHEAP - Sprawdź operacje na stercie)

komentarz 7 kwietnia 2023 przez j23 Mędrzec (194,920 p.)
edycja 8 kwietnia 2023 przez j23

No dobra, ale to nie jest przecież cały program, prawda? Błąd sterty może wystąpić podczas zwalniania pamięci w innym miejscu (np. funkcji niszczącej tę tablicę), a przyczyna problemu może być w jeszcze innym miejscu. W tej funkcji nie widzę błędu, a bez reszty kodu nic więcej nie da się napisać.

komentarz 8 kwietnia 2023 przez j23 Mędrzec (194,920 p.)
edycja 8 kwietnia 2023 przez j23

Dzisiaj zauważyłem, że w poprzednim poście jest link do kodu. Z pobieżnego oglądu nie widzę jakichś rażących błędów, ale jest coś, co może powodować błedy sterty:

int res=matrix_create(&m, width, height);
if(res==2){ // <--- !!!

    return 8;
}

...

matrix_destroy(&m); // <--- !!!

Nie wiem, czy to wykomentowanie funkcji main ma tutaj jakieś znaczenie, ale matrix_create zwraca 1, jeśli parametry są nieprawidłowe, w warunku sprawdzasz jedynie wartość 2, co oznacza problemy z alokacją, zatem istnieje ryzyko usuwania niestworzonej tablicy.

komentarz 8 kwietnia 2023 przez mokrowski Mędrzec (156,220 p.)

@j23 Problem w kodzie jest taki, że po alokacji kilku wierszy, błąd alokacji w następnym nie skutkuje zwolnieniem pamięci poprzednio udanych alokacji. Coś co w C++ załatwia RAII, w C trzeba obsłużyć ręcznie. BTW jest to jeden z kilku przypadków sensownego użycia goto w kodzie w C.

komentarz 8 kwietnia 2023 przez j23 Mędrzec (194,920 p.)

Zaraz, w kodzie, który tutaj wrzuciła, czyszczenie występuje (patrz linie 18-22). Nie pamiętam dokładnie jak było w matrix_create, ale było chyba podobnie jak w matrix_create_struct.

komentarz 10 kwietnia 2023 przez mokrowski Mędrzec (156,220 p.)
Racja. Tak czy siak valgrind i sanitizacja zgłasza błędy.
komentarz 10 kwietnia 2023 przez Oscar Nałogowiec (29,320 p.)
Należy też wzrócić uwagę na fakt, że tego typu bład może nie tylko powstać na skutek błędnego użycia free, ale i w przypadku, gdy nastąpiło zamazanie pamięci zaraz przez lub za zaallokowanym obszarem pamięci. Być może gdzieś pomylone są wiersze z kolumnami i jakiś zapis leci za daleko.

1 odpowiedź

0 głosów
odpowiedź 8 kwietnia 2023 przez mokrowski Mędrzec (156,220 p.)
Wydaje mi się że dostałaś odpowiedź na podobne pytanie tutaj: https://forum.pasja-informatyki.pl/583396/dynamiczna-tabliczka-mnozenia#a583404

Wystarczy adoptować rozwiązanie zwalniania pamięci z wymienionego posta (to ten sam problem).

Podobne pytania

0 głosów
1 odpowiedź 573 wizyt
pytanie zadane 19 listopada 2018 w C i C++ przez Roman1212 Początkujący (460 p.)
0 głosów
1 odpowiedź 231 wizyt
0 głosów
1 odpowiedź 454 wizyt
pytanie zadane 7 maja 2020 w C i C++ przez Hubertius Bywalec (2,970 p.)

92,675 zapytań

141,579 odpowiedzi

320,058 komentarzy

62,039 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

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!

...