2010-09-24 11 views

Odpowiedz

12

malloc przydziela pamięć. Zawartość pamięci zostaje pozostawiona tak jak jest (wypełniona tym, co było wcześniej).

calloc przydziela pamięć i ustawia jej zawartość na zero.

realloc zmienia rozmiar istniejącego przydzielonego bloku pamięci lub kopiuje zawartość istniejącego bloku pamięci do nowo przydzielonego bloku o żądanym rozmiarze, a następnie zwalnia stary blok.

Oczywiście, realloc jest sytuacją wyjątkową. Jeśli nie masz starego bloku pamięci, aby zmienić rozmiar (lub skopiować i zwolnić), nie ma powodu, aby z niego korzystać. Powodem, że malloc jest normalnie używany zamiast calloc jest to, że istnieje koszt uruchomienia do ustawiania pamięci na wszystkie zera i jeśli planujesz natychmiast wypełnić pamięć użytecznymi danymi (jak to często się dzieje), nie ma sensu najpierw go wyzerować.

Wszystkie te funkcje są standardowe i zachowują się niezawodnie w kompilatorach.

+2

'calloc' jest szczególnie użyteczny do alokowania tablic struktur, ponieważ wymaga 2 argumenty: 'calloc (num_of_items, size_of_item)'. Więcej pracy wymaga wypełnienia takiej tablicy przydatnymi danymi (jak mówi Tyler), więc istnieje spory argument za dodatkowym kosztem zainicjowania pamięci do znanej (zero) wartości. –

+2

'calloc' ma także tę zaletę, że wykonuje dla ciebie mnożenie, dzięki czemu w nie-błędnej implementacji sprawdzi i przestanie przepełniać. –

+0

Nie wspomniano o 'strdup' lub' asprintf', które również przydzielają pamięć. – abelenky

1

calloc jest prawdopodobnie właśnie wdrażane jako coś podobnego do:

void * calloc(size_t nmemb, size_t size) { 
     size_t len = nmemb * size); 
     void * ptr = malloc(len); 
     if (ptr) { 
      return memset(ptr, 0, len); 
     } 
     return ptr; 
} 

Więc to tylko dodaje pomnożyć przed i jasne po malloc.

malloc może być (ale prawdopodobnie nie jest w ogóle) realizowane jako:

void * malloc(size_t size) { 
     return realloc(NULL, size); 
} 

ponieważ można przekazać realloc wskaźnik NULL jak poprzedni wskaźnik, ale malloc najprawdopodobniej nie realizowane tak, bo to by spowolnić wszystkie mallocs i ponieważ realloc prawdopodobnie używa malloc.

Najważniejszą rzeczą na temat realloc jest to, że często jest w stanie określić rzeczywisty rozmiar bloku pamięci, który zwróciły wszystkie procedury przydzielania sterty i sprawdzić, czy blok jest wystarczająco duży, czy w niektórych przypadkach, jeśli najlepiej byłoby zmniejszyć blok lub przesunąć go.

void realloc(void * ptr, size_t size) { 
    size_t alen = MALLOC_LENGTH_OF(ptr); // this just stands for some method of determining 
            // the size of the block that was allocated, and could 
            // be looking it up in a table or looking at a place 
            // several bytes before the pointer, or some other 
            // implementation specific thing 
    if (0 == size) { 
     free(ptr); 
     return NULL; 
    } 
    if (alen >= size) { 
     return ptr; // big enough, and not worrying about it being too big 
    } 
    void new_ptr = malloc(size); // since I said that malloc most likely isn't 
           // implemented using realloc using malloc here is ok 
    if (new_ptr && ptr) { 
     memcpy(new_ptr, ptr, alen); 
    } 
    free(ptr); 
    return new_ptr; 
} 

Malloc jest używany częściej, ponieważ jest najprostszy. Programiści często mogą na tyle dużą ilość alokacji, aby zacząć od tego, że nie muszą się martwić o zmianę ich rozmiaru za pomocą realloc, a bardzo często czyszczenie pamięci nie jest potrzebne.

Istnieją różne zachowania między różnymi bibliotekami, a nawet można łączyć programy z innymi wersjami, aby uzyskać takie zachowanie bez (zwykle bez zmiany kompilatora).

Niektóre biblioteki malloc służą do debugowania i wykrywania błędów. Inni mogą oferować lepszą wydajność.Niektóre są zoptymalizowane do przydzielania pamięci dla kilku różnych wątków w tym samym czasie i unikają różnych wątków wymagających zablokowania całej sterty, aby wykonać alokację lub bezpłatnie.

Wszystkie powinny jednak zapewniać tę samą semantykę z perspektywy aplikacji.

+0

Głosuj za używanie początkowych nawiasów klamrowych w tym samym wierszu, co blok!(niezupełnie) – Firoso

+0

@Firoso: Dzięki temu _diff_ daje lepsze wyniki przy porównywaniu wersji, a także zmniejsza kod. Ponieważ używam również nawiasów klamrowych wokół jednego bloku liniowego, naprawdę pomaga umieścić je na tej samej linii, co kod otwierający blok. – nategoose

+0

jeśli chodzi o opcję diff -p, uważam, że heurystyczna jest to, że wiersz zawiera nazwę funkcji, jeśli ma litery w kolumnie 1. – ninjalj

3

Oprócz tych, które masz wymieniających (niektóre są Extensions):

  • zmienne na stosie są dynamicznie przydzielane. Rekursja to sposób na przydzielenie i wykorzystanie tego.
  • C99 ma zmiennej długości tablice (jak wspomina BlueRaja).
  • W niektórych systemach masz nawet wywołanie alloca, które umożliwia przydzielanie porcji o zmiennej długości w ramce stosu.
  • POSIX ma odwzorowanie segmentów pamięci i plików, z kombinacjami shm_open lub open i mmap.
  • SysV IPC ma shmget itp wzywa
+0

System Windows ma również sposoby udostępniania pamięci między procesami i plików map w pamięci. – RBerteig

2

jedna metoda przydzielania pamięci, która nie została wymieniona jest alloca(size_t size) który zastrzega rozmiar bajtów pamięci na bieżącej ramce stosu i automatycznie zwalnia pamięć ponownie po opuszczeniu stos rama.

0

malloc: pozwala powiedzieć, że masz ptr = (int *) malloc (10); Przydziela 10 ciągłych bajtów pamięci, a adres pierwszego bajtu jest przechowywany w zmiennej wskaźnika ptr. Przydzielona pamięć zawiera teraz wartość śmieci.
Więc jeśli zmienię od 0 do 3 scanf ("% d", ptr + i); przechowuje 4 liczby całkowite w 4 sąsiadujących lokalizacjach. ptr ma adres pierwszej liczby całkowitej, ptr + 1 ma adres drugiego numeru i tak dalej. Stąd printf ("% d", atstrick (ptr + i)); wydrukuje odpowiednie wartości. W przeciwieństwie do pamięci alokowanej dla zmiennych i tablic, przydzielane dynamicznie nie ma powiązanej z nią nazwy. Jak widać powyżej.

calloc: Jest to podobne do malloc wyjątkiem różnicy w dwóch: 1. Wyjaśnienie: PTR = (int *) calloc (5, sizeof (int)); Tutaj mamy dwa argumenty, 5 to żaden z bloków przydzielonych i drugi argument jest równy 4 bajtom. Jest to równoważne ptr = (int *) malloc (5 * sizeof (int)); 2.Inoc alokacja pamięci wywołania nie jest śmieciem, ale jest 0. Zarówno malloc, jak i calloc zwracają NULL, jeśli nie ma wystarczającej ilości pamięci dostępnej w sterty.

Powiązane problemy