2010-03-30 3 views

Odpowiedz

4

Niekoniecznie.

Często robi jak z link that munissor posted, ale strona, Mac OS 10.5 człowiek mówi:

Jeśli rozmiar wynosi zero i ptr nie jest równe NULL, nowy, minimalne wielkości obiekt jest przydzielona i oryginalny obiekt jest uwolniony.

Co to jest "obiekt o minimalnej wielkości"? Cóż, każdy alokator przechowuje pewne informacje o alokacjach, a to zajmuje miejsce, które często jest przydzielane jako dodatek do miejsca zarezerwowanego dla użytkownika. Przypuszczalnie "obiekt o minimalnej wielkości" to tylko jeden z tych nagłówków plus zero bajtów przestrzeni zarezerwowanej dla użytkownika.

Zgaduję, że ten zapis jest obecny w celu wsparcia wdrożeń, które istniały w czasie standaryzacji, i że te implementacje są przydatne do debugowania zachowania przydziału.


Aby rozwiązać Jonathan's comments

Rozważmy różnicę między

for (int i=0; i<VERY_BIG_NUMBER; ++i){ 
    char *p = malloc(sizeof(char[10])); 
    free(p); 
} 

i

for (int i=0; i<VERY_BIG_NUMBER; ++i){ 
    char *p = malloc(sizeof(char[10])); 
    realloc(p,0); 
} 

Z sane realizacji malloc i free pierwszy klip robi nie zużywają pamięć bez ograniczeń. Ale jeśli implementacja realloc zwróci te "obiekty o minimalnym rozmiarze", może.

Z pewnością ten przykład jest wymyślny i polega na zrozumieniu, co rozumiemy przez "obiekt o minimalnym rozmiarze", ale myślę, że tekst na to pozwala.

Krótko mówiąc, jeśli oznaczafree powinieneś powiedzieć free.

+0

Tak, znalazłem to samo oświadczenie tutaj: http://www.manpagez.com/man/3/realloc/ –

+1

Myślę, że te implementacje NIE są zgodne ze specyfikacją C. Zajrzyj także pod http://www.opengroup.org/onlinepubs/009695399/functions/realloc.html – munissor

+1

@munissor: To zachowanie jest zgodne. Ze specyfikacji POSIX: "Jeśli rozmiar wynosi 0, albo wskaźnik zerowy, albo ** unikalny wskaźnik, który może być pomyślnie przekazany do wolnego() ** zostanie zwrócony" (nacisk mój). Jest również zgodny z językiem w standardzie C. –

8

Może to być lub nie być równoważne z wywołaniem free na wskaźniku; wynik jest zdefiniowany przez implementację.

ze standardu C99 (§7.20.3/1):

Jeśli wielkość przestrzeni wymagane jest zero, zachowanie jest realizacja zdefiniowane: albo zerowy wskaźnik jest zwracany, lub zachowanie jest tak, jakby rozmiar był pewną niezerową wartością, z wyjątkiem tego, że zwracany wskaźnik nie jest używany do uzyskania dostępu do obiektu.

Dotyczy to wszystkich funkcji zarządzania pamięcią, w tym realloc.

+1

Jest to odpowiednik dzwonienia za darmo, ponieważ oryginalna pamięć nie jest już dostępna. Zobacz także moją odpowiedź - która cytuje informacje z § 7.20.3.4 (realloc) oraz cytowany fragment. Materiał w §7.20.3.4 nadpisuje ogólny komentarz - lub raczej określa, że ​​'realloc()' zwalnia - zwalnia - oryginalną pamięć, a następnie wykonuje ekwiwalent 'malloc()' dla nowego rozmiaru, który jest równoważny do 'malloc (0)' w tym przypadku, a następnie dostaje twoje cytowane zachowanie.Rozróżnienie ** key ** polega na tym, że 'realloc()' bezwarunkowo zwalnia starą pamięć. –

+3

@ Jonathan: Jeśli zachowanie jest "tak, jakby rozmiar miał pewną niezerową wartość", niepowodzenie zwolnienia wskaźnika spowodowałoby przeciek pamięci. W takim przypadku nie jest to równoznaczne z dzwonieniem za darmo na wskaźniku. –

1

Tak

Standard C99 §7.20.3.4 (realloc) mówi:

Funkcja realloc dealokuje starego obiektu wskazywanego przez ptr i zwraca wskaźnik do nowego obiektu, który ma rozmiar określony według rozmiaru. Zawartość nowego obiektu będzie taka sama, jak obiektu starego obiektu przed deallokacją, aż do mniejszego z nowych i starych rozmiarów. Wszystkie bajty w nowym obiekcie przekraczające rozmiar starego obiektu mają nieokreślone wartości.

Jeśli ptr jest wskaźnikiem pustym, funkcja realloc zachowuje się jak funkcja malloc dla określonego rozmiaru . W przeciwnym razie, jeśli ptr nie pasuje do wskaźnika wcześniej zwróconemu przez funkcję calloc, malloc lub realokacja , lub jeśli przestrzeń została zwolniona przez wywołanie na funkcję wolną lub ponowną, zachowanie jest niezdefiniowane. Jeśli nie można przydzielić pamięci dla nowego obiektu , stary obiekt nie zostanie zwolniony, a jego wartość pozostaje niezmieniona.

To wyraźnie stwierdza, że ​​stary obiekt jest zwolniony (uwolniony). Wartość zwracana może być zerowy wskaźnik, lub może to być wartość, jak określono w uwagach ogólnych do §7.20.3:

Jeśli wielkość przestrzeni wymagane jest zero, zachowanie jest realizacja zdefiniowane: zwracany jest wskaźnik zerowy lub zachowanie jest takie, jakby wielkość była niezerową wartością inną niż , z tym że zwracany wskaźnik nie będzie używany do uzyskiwania dostępu do obiektu.

Tak czy inaczej, nie dereference wartość zwracana może: to może być wykorzystane jako argument do free() lub przekazywane do innych funkcji, jak długo oni z kolei nie odwoływać.

+2

Jest oczywiste, że istniejące dane nie są już dostępne. Nie jest jednak jasne, czy cała pamięć przydzielona przez pierwotne wywołanie jest zwracana: alokator może utrzymywać unikatowy i niemożliwy do odzyskania rekord dla przydziału o zerowej wielkości. – dmckee

Powiązane problemy