2013-03-08 20 views
6

Jestem w trakcie trwania projektu i próbuję użyć malloc() i realloc(). Wiem, kiedy malloc, to działa, ale kiedy używam realloc, to w ogóle nie zmienia ilości przydzielonej pamięci. Zawsze jednak, że ten realloc ponownie przydzieli twoją już wyciśniętą pamięć.Pamięć nie przenosi się ponownie

Oto co mam:

obejmować:

#include <stdlib.h> 

Mam struct:

struct student { 
    int age; 
    int numOfClasses; 
    int gender; //0 male; 1 female 
} student; 

Kiedy chcę zrobić 7 z tych strukturach za pomocą malloc, będę użyj poniższego kodu:

student stud* = (structure*) malloc(7*sizeof(student)); 

Ta linia działa. Ten wiersz kodu przyjmuje rozmiar struktury i mnożników przez 7. W skrócie, to chwyci wystarczającą ilość pamięci, aby utworzyć tablicę złożoną z 7 struktur.

Teraz, jeśli chcę zmienić na 8, chciałbym to zrobić gdzie A jest poprzednia pamięć malloced i B jest nowy malloced (lub realloced) Pamięć:

enter image description here

Oto jak mam go w kodzie:

stud = (student*)realloc(stud, 8*sizeof(student)); 

Z tego, co wiem, realloc bierze zmienną w drugim parametrze i mallocs, że ilość pamięci. Następnie pobiera wskaźnik (lub poprzedni malloced) i wypełnia właśnie malloced memory ile można z danego wskaźnika. Oczywiście drugi parametr musi być większy niż poprzedni rozmiar malloced, lub stud straci trochę pamięci na końcu. Teraz to jest mój problem. Kiedy zadzwonię do powyższej linii, nic nie zmienia. Szeroka tablica zachowuje długość 7 lat. Jestem prawie pewna, że ​​mam wystarczająco dużo pamięci, aby móc ją ponownie wykorzystać.

Czy robię to dobrze? Gdzie może być mój problem?

+8

Co sprawia, że ​​tablica malloced wciąż ma długość 7? –

+0

Nie dotyczy to twojego problemu, ale myślę, że twoja struktura doskonale nadaje się do 'wyliczenia '. – teppic

Odpowiedz

11

Twoje zrozumienie zachowania realloc jest prawie poprawne. To nie ma mieć, aby zwrócić inny wskaźnik; może być tak, że po początkowym bloku była wystarczająca ilość niewykorzystanej pamięci, więc menedżer sterty może po prostu zwrócić ten sam wskaźnik do ciebie (ale dostosować swój wewnętrzny stan, tak aby wiedział, że blok jest teraz większy).

Ale popełniłeś jeden mały błąd.

stud = (student*)realloc(stud, 8*sizeof(student)); 

Tutaj wymieniasz wskaźnik stud o wartości powrotnej z realloc. Jeśli zdarzy się, że zwróci NULL z powodu braku głodu pamięci, utracisz oryginalny wskaźnik stud, a pamięć wycieknie. Zamiast tego należy użyć tymczasowego wskaźnika.

tmp = realloc(stud, 8*sizeof(student)); 
if (tmp) 
    stud = tmp; 

Należy również pamiętać, że nadal trzeba włożyć coś do ósmego gniazda. Po realloc ósmy slot jest prawidłową alokowaną pamięcią, ale zawiera śmieci, dopóki nie zapiszesz w niej czegoś znaczącego.

+0

Jestem prawie pewien, że jest wystarczająco dużo pamięci, aby móc ponownie przydzielić. –

+1

OK, ale nadal nie wyjaśniłeś, dlaczego uważasz, że tablica malloced wciąż ma długość 7. –

+0

To jest rzecz, nie wiem, dlaczego nie jest przydzielanie od 7 do 8. –

4

To powinno działać, mimo że mam te zalecenia:

Nie rzucać powrót z malloc. Jest bezużyteczny w C i może ukrywać, że zapomniałeś dołączyć <stdlib.h>.

Nie używaj ptr = realloc (ptr, ...), ponieważ tworzy to przeciek pamięci w przypadku, gdy ponowne wysłanie zwraca NULL. Zamiast tego należy użyć

if ((new_ptr = realloc (stud, 8 * sizeof (*stud))) != NULL) { 
    stud = new_ptr; 
} else { 
    scream_and_die("out of memory"); 
} 

I używać sizeof (*stud), to znaczy odwoływać wyrażenie używając wskaźnik, nie typu wskazywanego (być niezależne od konkretnego rodzaju wskaźnik przydzielić). W ten sposób, gdy zmienisz nazwę na typedef, linia malloc/realloc nie wymaga modyfikacji. Innymi słowy, najlepsza praktyka dynamicznej alokacji pamięci w C jest dla tablicy N czymś, co jest .