Skąd free wie ile za darmo?

W programowaniu C, moĹźesz przekazaÄ ‡ dowolny rodzaj wskaznika jako argument do free, skÄ ... d zna on Rozmiar przydzielonej pamiÄ ™ ci do free? Ilekroć przekazuję wskaźnik do jakiejś funkcji, muszę również przekazać rozmiar (tzn. tablica 10 elementów musi otrzymać 10 jako parametr, aby poznać rozmiar tablicy), ale nie muszę przekazywać rozmiaru do funkcji swobodnej. Dlaczego nie i czy mogę użyć tej samej techniki w moich własnych funkcjach, aby uchronić mnie przed potrzebą wózka wokół dodatkowej zmiennej o długości tablicy?

Author: Prashant Kumar, 2009-10-05

11 answers

Gdy wywołujesz malloc(), określasz ilość pamięci do przydzielenia. Ilość faktycznie użytej pamięci jest nieco większa i zawiera dodatkowe informacje, które rejestrują (przynajmniej)jak duży jest blok. Nie możesz (niezawodnie) uzyskać dostępu do tych innych informacji - i nie powinieneś: -).

Kiedy wywołujesz free(), Wystarczy spojrzeć na dodatkowe informacje, aby dowiedzieć się, jak duży jest blok.

 284
Author: Gary McGill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-18 06:32:18

Większość implementacji funkcji alokacji pamięci C przechowuje informacje księgowe dla każdego bloku, zarówno w linii, jak i osobno.

Jednym z typowych sposobów (in-line) jest przydzielenie zarówno nagłówka, jak i pamięci, o którą prosiłeś, wyściełanej do pewnego minimalnego rozmiaru. Na przykład, jeśli poprosiłeś o 20 bajtów, system może przydzielić 48-bajtowy blok:

  • 16-bajtowy nagłówek zawierający rozmiar, specjalny znacznik, sumę kontrolną, wskaźniki do następnego / poprzedniego bloku i tak dalej.
  • 32 bajtów obszaru danych (twoje 20 bajtów padded out do wielokrotności 16).

Podany adres jest adresem obszaru danych. Następnie, gdy uwolnisz blok, free po prostu pobierze adres, który mu podasz i, zakładając, że nie wypełniłeś tego adresu lub pamięci wokół niego, sprawdź informacje księgowe bezpośrednio przed nim. Graficznie byłoby to na wzór:

 ____ The allocated block ____
/                             \
+--------+--------------------+
| Header | Your data area ... |
+--------+--------------------+
          ^
          |
          +-- The address you are given

Należy pamiętać, że rozmiar nagłówka i wyściółki są całkowicie zaimplementowane defined (w rzeczywistości całość jest zdefiniowana przez implementację (a) , ale opcja księgowania in-line jest powszechna).

Sumy kontrolne i specjalne znaczniki, które istnieją w informacjach księgowych, są często przyczyną błędów, takich jak "Arena pamięci uszkodzona" lub "podwójnie wolna", jeśli je nadpisujesz lub zwolnisz dwa razy.

Padding (aby zwiększyć efektywność alokacji) jest dlaczego czasami można napisać trochę poza końcem żądanej przestrzeni bez powodowania problemy (mimo to, nie rób tego, to nieokreślone zachowanie i to, że czasami działa, nie znaczy, że jest w porządku, aby to zrobić).


(a) napisałem implementacje malloc w systemach wbudowanych, gdzie masz 128 bajtów bez względu na to, o co prosisz (był to Rozmiar największej struktury w systemie), zakładając, że prosisz o 128 bajtów lub mniej (żądania o więcej będą spełnione z wartością zwracaną NULL). Bardzo prosta maska bitowa (tzn. nie w linii) została użyta do decydowania czy przydzielono 128-bajtowy fragment, czy nie.

Inne, które opracowałem, miały różne pule dla 16-bajtowych, 64-bajtowych, 256-bajtowych i 1K, ponownie używając maski bitowej, aby zdecydować, które bloki zostały użyte lub dostępne.

Obie te opcje zdołały zmniejszyć obciążenie informacji księgowych i zwiększyć szybkość malloc i free (nie trzeba łączyć sąsiednich bloków podczas uwalniania), szczególnie ważne w środowisku, w którym pracowaliśmy.

 115
Author: paxdiablo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-17 02:00:59

Z listy comp.lang.c FAQ: Skąd free wie ile bajtów do uwolnienia?

Implementacja malloc / free zapamiętuje rozmiar każdego bloku w miarę jego alokacji, więc nie jest konieczne przypominanie jej o rozmiarze podczas zwalniania. (Zazwyczaj rozmiar jest przechowywany obok przydzielonego bloku, dlatego rzeczy zwykle źle się psują, jeśli granice przydzielonego bloku są nawet nieznacznie przekroczone)

 43
Author: jdehaan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-21 10:47:56

Ta odpowiedź jest przeniesiona z skąd free () wie ile pamięci ma deallokować? gdzie nie mogłem odpowiedzieć pozornym duplikatem pytania. Odpowiedź ta powinna być zatem istotna dla tego duplikatu:


W przypadku malloc, alokator sterty przechowuje mapowanie oryginalnego zwracanego wskaźnika, do istotnych szczegółów potrzebnych do free późniejszego użycia pamięci. Zazwyczaj wiąże się to z przechowywaniem wielkości obszaru pamięci w dowolnej formie, która ma znaczenie dla używany alokator, na przykład rozmiar surowy lub węzeł w drzewie binarnym używany do śledzenia alokacji lub liczba używanych "jednostek" pamięci.

free nie zawiedzie, jeśli "zmienisz nazwę" wskaźnika lub powielisz go w jakikolwiek sposób. Nie jest on jednak liczony i tylko pierwsza free będzie poprawna. Dodatkowe freeS są "podwójnie wolne" błędy.

Próba użycia free dowolnego wskaźnika o wartości innej niż zwrócona przez poprzednie malloc s, a jeszcze nie odtworzona, jest błędem. Nie jest możliwe częściowe zwolnienie regionów pamięci zwróconych z malloc.

 6
Author: Matt Joiner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:31

W powiązanej notatce GLib biblioteka posiada funkcje alokacji pamięci, które nie zapisują domyślnego rozmiaru - a następnie po prostu przekazujesz parametr size do free. Może to wyeliminować część napowietrznych.

 4
Author: EFraim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-05 08:07:11

malloc() i free() są zależne od systemu/kompilatora, więc trudno jest udzielić konkretnej odpowiedzi.

Więcej informacji na temat tego drugiego pytania .

 3
Author: LiraNuna,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:14

Menedżer sterty przechowywał gdzieś ilość pamięci należącą do przydzielonego bloku, kiedy wywołałeś malloc.

Nigdy nie zaimplementowałem żadnego, ale domyślam się, że pamięć tuż przed przydzielonym blokiem może zawierać metainformacje.

 2
Author: Timbo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-05 07:48:20

Aby odpowiedzieć na drugą połowę twojego pytania: tak, możesz, a dość powszechny Wzór W C jest następujący:

typedef struct {
    size_t numElements
    int elements[1]; /* but enough space malloced for numElements at runtime */
} IntArray_t;

#define SIZE 10
IntArray_t* myArray = malloc(sizeof(intArray_t) + SIZE * sizeof(int));
myArray->numElements = SIZE;
 1
Author: MSalters,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-05 08:02:53

Oryginalną techniką było przydzielenie nieco większego bloku i zapisanie rozmiaru na początku, a następnie przekazanie aplikacji reszty bloga. Dodatkowa przestrzeń zawiera rozmiar i ewentualnie linki do wątku wolnych bloków razem do ponownego użycia.

Istnieją jednak pewne problemy z tymi sztuczkami, takie jak słabe zachowanie pamięci podręcznej i zarządzania pamięcią. Korzystanie z pamięci bezpośrednio w bloku ma tendencję do niepotrzebnego stronicowania rzeczy, a także tworzenia brudnych stron, które komplikują udostępnianie i kopiowanie przy zapisie.

Więc bardziej zaawansowaną techniką jest utrzymywanie osobnego katalogu. Opracowano również metody egzotyczne, w których obszary pamięci wykorzystują tę samą moc dwóch rozmiarów.

Ogólnie rzecz biorąc, odpowiedź brzmi: oddzielna struktura danych jest przydzielana do zachowania stanu.

 1
Author: DigitalRoss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-03 20:38:12

Pamięć przydzielona za pomocą malloc() lub calloc () lub realloc ().

Void free (void * ptr);

Funkcja free nie akceptuje rozmiaru jako parametru. Skąd funkcja free () wie, ile pamięci należy zwolnić, biorąc pod uwagę tylko wskaźnik?

Poniżej znajduje się najczęstszy sposób przechowywania wielkości pamięci tak, aby free() wiedział, jaki rozmiar pamięci ma być dealokowany.

Gdy alokacja pamięci jest wykonywana, rzeczywista przydzielona przestrzeń sterty jest o jedno słowo większa niż żądana pamięć. Extra word jest używany do przechowywania wielkości alokacji i jest później używany przez free ()

 1
Author: geetha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-26 07:25:04

Kiedy wywołujemy malloc, to po prostu zużywa więcej bajtów z jego wymagań. To większe zużycie bajtów zawiera informacje takie jak suma kontrolna,rozmiar i inne dodatkowe informacje. Kiedy dzwonimy za darmo w tym czasie to bezpośrednio przejść do tej dodatkowej informacji, gdzie to znaleźć adres, a także dowiedzieć się, ile blok będzie wolny.

 0
Author: Varun Chhangani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-18 16:15:00