2012-12-25 17 views
5

uczę tej funkcji malloc i mogę korzystać z niektórych pomocy:malloc i nieważne Wskaźniki

static void *malloc(int size) 
    { 
     void *p; 

     if (size < 0) 
       error("Malloc error"); 
     if (!malloc_ptr) 
       malloc_ptr = free_mem_ptr; 

     malloc_ptr = (malloc_ptr + 3) & ~3;  /* Align */ 

     p = (void *)malloc_ptr; 
     malloc_ptr += size; 

     if (free_mem_end_ptr && malloc_ptr >= free_mem_end_ptr) 
       error("Out of memory"); 

     malloc_count++; 
     return p; 
} 

wiem, że malloc func przydziela pamięć dla dowolnego typu, jeśli jest wystarczająco dużo pamięci, ale linie Nie rozumiem, że:

p = (void *)malloc_ptr; 
malloc_ptr += size; 

Jak może wskazywać na taki typ danych? Po prostu nie mogę zrozumieć tego pustego wskaźnika ani jego lokalizacji.

UWAGA: malloc_ptr jest niepodpisany długo

+0

Ten kod zawiera założenie, że wskaźnik do 'unsigned long' (czyli' malloc_ptr') może również wskazać do dowolnego innego obiektu, z punktu widzenia wyrównania. To założenie nie zawsze jest prawdziwe (na przykład w niektórych systemach może nie być w stanie wskazać obiektów 'long double'). –

+0

Kod zakłada, że ​​żaden typ nie wymaga bardziej rygorystycznego wyrównania niż czterobajtowe wyrównanie. Kod nie pokazuje, w jaki sposób zainicjowano 'free_mem_ptr' i' free_mem_end_ptr'. Nie zwraca wartości NULL, gdy nie ma więcej miejsca. Jeśli funkcja 'error()' powróci, wtedy całe piekło się rozpadnie. –

Odpowiedz

5

Powodem zwraca void wskaźnik dlatego, że nie ma pojęcia, co się podziału przestrzeni w zaproszeniu malloc. Wszystko, co wie, to ilość miejsca, o które prosiłeś. To ty lub twój kompilator decydujesz, co zapełni pamięć. Lokalizacja pustego wskaźnika jest zazwyczaj implementowana jako lista połączona w celu zachowania integralności i poznania, jakie wartości pamięci są wolne, co jest zaskakująco utrzymywane w funkcji free.

+0

, ale skąd wiadomo, ile miejsca należy przeznaczyć? w jaki sposób wykorzystuje wartość rozmiaru? Po prostu tego nie widzę. Na przykład mam struct z 8 ints 3 chars i 1 float, zwane mystruct, i teoretycznie powinno to zająć dużo miejsca w pamięci, ale po prostu nie mogę zrozumieć, w jaki sposób – morcillo

+0

@ morcillo W takim przypadku prawdopodobnie używałbyś '' sizeof' operator, który wyznaczy prawidłowy rozmiar w bajtach potrzebny do poprawnego przydzielenia deklarowanej struktury. – squiguy

+0

Wiem, że sizeof jest do tego, ale nie rozumiem, jak to zrobić, aby przydzielić miejsce w pamięci. malloc_ptr ma rozmiar typu, ale w jaki sposób p = (void *) malloc_ptr wie, aby przydzielić 8 bajtów, 2 bajty lub 152 bajty? czy odlewanie do funkcji malloc powoduje, że działa? (my_struct *) malloc (sizeof (my_struct))? – morcillo

1

Malloc zwraca wskaźnik dla fragmentu całkowicie niestrukturalnej, płaskiej pamięci. Wskaźnik (void *) oznacza, że ​​nie ma pojęcia, na co wskazuje (brak struktury), a jedynie wskazuje na pamięć wielkości.

Poza rozmową do malloc, możesz powiedzieć programowi, że wskaźnik ten ma jakąś strukturę. To znaczy, jeśli masz strukturę some_struct, możesz powiedzieć: .

Zobacz, jak malloc zna rozmiar tego, co zamierza przydzielić, ale w rzeczywistości nie zna jego struktury? Twoje wezwanie do malloc nie przekazuje żadnych informacji o strukturze, a jedynie rozmiar ilości pamięci do przydzielenia.

Jest to sposób bycia typowym: malloc zwraca pewną ilość pamięci i Twoim zadaniem jest przesłać ją do pamięci strukturalnej, której potrzebujesz.

1

To jest implementacja z malloc, więc wolno robić rzeczy, które nie byłyby uzasadnione w zwykłym programie. W szczególności wykorzystuje przekształcenie zdefiniowane w ramach implementacji z unsigned long do void *. Zestaw inicjujący programu ustawia malloc_ptr na numeryczny adres dużego bloku nieprzydzielonej pamięci. Następnie, gdy poprosisz o przydział, malloc usunie wskaźnik z bieżącej wartości malloc_ptr i zwiększy malloc_ptr o liczbę żądanych bajtów. W ten sposób przy następnym wywołaniu malloc zwróci on nowy wskaźnik.

Chodzi o najprostszą możliwą implementację malloc. Przede wszystkim wydaje się, że nigdy więcej nie korzysta z uwolnionej pamięci.

1
p = (void *)malloc_ptr; 

`malloc` returns a void pointer, which indicates that it is a pointer to a region of 
unknown data type. The use of casting is only required in C++ due to the strong type 
system, whereas this is not the case in C. The lack of a specific pointer type 
returned from `malloc` is `type-unsafe` behaviour according to some programmers: 
malloc allocates based on byte count but not on type. 

malloc_ptr += size; 

`C` implicitly casts from and to `void*`, so the cast will be done automatically. In 
`C++` only conversion to void* would be done implicitly, for the other direction an 
explicit cast is required. 

Wiki wyjaśnienie o rodzaju casting,

`malloc` function returns an untyped pointer type `void *`, which the calling code must 
cast to the appropriate pointer type. Older C specifications required an explicit cast 
to do so, therefore the code `(struct foo *) malloc(sizeof(struct foo))` became the 
accepted practice. However, this practice is discouraged in ANSI C as it can mask a 
failure to include the header file in which `malloc` is defined, resulting in 
downstream errors on machines where the int and pointer types are of different sizes, 
such as the now-ubiquitous x86_64 architecture. A conflict arises in code that is 
required to compile as C++, since the cast is necessary in that language. 
1

Jak widać to zarówno linie,

p = (void *)malloc_ptr; 
malloc_ptr += size; 

tutaj masz malloc_ptr typu unsigned long więc jesteśmy typu odlew ta zmienna anulować typ, a następnie zapisać go w p. iw podobny sposób drugi oznacza malloc_ptr = malloc_ptr + size;

A oba te kody są dla wygody programisty, ponieważ p jest typu void wskaźnik, więc w aplikacji, gdy używasz malloc, nie wiesz, który typ bloku pamięci musi być zwracany przez funkcję, więc ta funkcja zawsze zwraca to ogólna pusta wskazówka, abyśmy mogli ponownie wpisać typografię w naszej aplikacji zgodnie z wymaganiami.

i samo w drugim kodzie jeśli wprowadź wielkość w ujemny, to co się dzieje z tym warunkiem

if (free_mem_end_ptr && malloc_ptr >= free_mem_end_ptr) 
error("Out of memory");