Zauważyłem, że niektóre osoby i odniesienia, takie jak książki, stwierdzają, że jeśli p != NULL
i p
pochodzą z poprzedniej alokacji (np. Przez malloc
), to realloc(p, 0)
jest równoważne free(p)
na GNU/Linux. Aby wesprzeć tę tezę man realloc
stany dokładnie w ten sposób (Kopalnia nacisk idzie do przodu):Czy realloc (p, 0) naprawdę obejmuje darmowe (p) w glibc?
Funkcja realloc() zmienia rozmiar bloku pamięci wskazywanego przez ptr do size bajtów. Zawartość pozostanie niezmieniona w zakresie od początku regionu do minimum starych i nowych rozmiarów. Jeśli nowy rozmiar jest większy niż stary rozmiar, dodana pamięć nie zostanie zainicjowana. Jeśli ptr ma wartość NULL, wywołanie jest równoważne malloc (rozmiar) dla wszystkich wartości wielkości; jeśli rozmiar jest równy zeru, a ptr nie ma wartości NULL, wówczas wywołanie jest równoważne bezpłatnemu (ptr). Jeśli ptr nie ma wartości NULL, musi zostać zwrócone przez wcześniejsze wywołanie metody malloc(), calloc() lub realloc(). Jeśli wskazany obszar został przeniesiony, wykonywany jest bezpłatny (ptr) .
Jak można znaleźć w this question, norma C nie określa dokładnie, co powinno się stać, a rzeczywiste zachowanie jest zdefiniowane w ramach implementacji. Dokładniej:
C11 §7.22.3/P1 funkcje zarządzania pamięcią mówi:
Jeśli wielkość przestrzeni wymagane jest zero, zachowanie jest wdrożenie zdefiniowane: albo null wskaźnik jest zwracany, lub zachowanie zachowuje się tak, jakby wielkość miała pewną wartość różną od zera, z tym wyjątkiem, że zwracany wskaźnik nie będzie używany do uzyskania dostępu do obiektu.
i C11 §7.22.3.5 Funkcja realloc zawiera:
3) (...) Jeśli pamięć dla nowego obiektu nie można przyporządkować, stary obiekt jest nierozdzielone i jego wartość jest niezmieniona.
4) Funkcja
realloc
zwraca wskaźnik do nowego obiektu (co może mają taką samą wartość jak wskaźnik do starego obiektu), lub null pointer jeśli nowy obiekt nie może być przydzielona.
pisałem kilka podstawowych kod, aby dowiedzieć się rzeczywiste zachowanie z pomocą mcheck
, sprawdzający pamięci, który jest dostarczany wraz glibc
:
#include <mcheck.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int a = 5;
int *p, *q;
mtrace();
p = malloc(sizeof(int));
q = &a;
printf("%p\n", (void *) p);
printf("%p\n", (void *) q);
q = realloc(p, 0);
printf("%p\n", (void *) p);
printf("%p\n", (void *) q);
return 0;
}
i wyniki są następujące:
$ gcc -g check.c
$ export MALLOC_TRACE=report
$ ./a.out
0xfd3460
0x7ffffbc955cc
0xfd3460
(nil)
[[email protected] workspace]$ mtrace a.out report
Memory not freed:
-----------------
Address Size Caller
0x0000000000fd3460 0x4 at /home/grzegorz/workspace/check.c:12
jak ty może zobaczyć q
został ustawiony na NULL
. Wygląda na to, że free()
nie zostało tak naprawdę wywołane. W rzeczywistości to nie może być chyba moja interpretacja jest błędna: od realloc
powrócił NULL
wskaźnik, nowy obiekt może nie zostały przydzielone, co oznacza, że:
stary obiekt nie jest zwalniane, a jej wartość nie ulega zmianie
Czy to prawda?
Sformułowanie o 'realloc (ptr, 0)' będącym odpowiednikiem 'free (ptr)' było używane w POSIX, ale [oficjalne referencje POSIX 'realloc'] (http: //pubs.opengroup. org/onlinepubs/9699919799/functions/realloc.html) używa teraz języka ze standardu C. Standard POSIX mówi jednak "jeśli' realloc() 'zwraca zerowy wskaźnik, spacja wskazywana przez p nie została zwolniona". –