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

Dynamiczna alokacja pamięci

Aruba Cloud VPS - 50% taniej przez 3 miesiące!
0 głosów
437 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 (195,260 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 (195,260 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 (195,260 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,320 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 (195,260 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,320 p.)
Racja. Tak czy siak valgrind i sanitizacja zgłasza błędy.
komentarz 10 kwietnia 2023 przez Oscar Nałogowiec (29,340 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,320 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ź 641 wizyt
pytanie zadane 19 listopada 2018 w C i C++ przez Roman1212 Początkujący (460 p.)
0 głosów
1 odpowiedź 265 wizyt
0 głosów
1 odpowiedź 574 wizyt
pytanie zadane 7 maja 2020 w C i C++ przez Hubertius Bywalec (2,970 p.)

93,173 zapytań

142,184 odpowiedzi

321,967 komentarzy

62,499 pasjonatów

Advent of Code 2024

Top 15 użytkowników

  1. 1149p. - dia-Chann
  2. 1131p. - Łukasz Piwowar
  3. 1124p. - CC PL
  4. 1118p. - Łukasz Eckert
  5. 1097p. - Michal Drewniak
  6. 1081p. - Marcin Putra
  7. 1076p. - rucin93
  8. 1054p. - Adrian Wieprzkowicz
  9. 1047p. - Piotr Aleksandrowicz
  10. 1000p. - ssynowiec
  11. 967p. - rafalszastok
  12. 931p. - Michał Telesz
  13. 886p. - Dominik Łempicki (kapitan)
  14. 842p. - Dawid128
  15. 819p. - Mariusz Fornal
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! ♡

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

Wprowadzenie do ITsec, tom 1 Wprowadzenie do ITsec, tom 2

Można już zamawiać dwa tomy książek o ITsec pt. "Wprowadzenie do bezpieczeństwa IT" - mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy aż 15% zniżki! Dziękujemy ekipie Sekuraka za fajny rabat dla naszej Społeczności!

...