2014-09-11 12 views
5

Gdy system operacyjny ładuje proces do pamięci, inicjuje wskaźnik stosu do adresu wirtualnego, w którym zdecydował, gdzie powinien iść stos w wirtualnej przestrzeni adresowej procesu, a kod programu używa tego rejestru, aby wiedzieć, gdzie znajdują się zmienne stosu. Moje pytanie brzmi: w jaki sposób malloc() wie, na jakim wirtualnym adresie zaczyna się hałda? Czy sterty zawsze istnieją na końcu segmentu danych, jeśli tak, to jak funkcja malloc() wie, gdzie to jest? Czy jest to nawet jeden ciągły obszar pamięci lub po prostu losowo przeplatany z innymi zmiennymi globalnymi w sekcji danych?W jaki sposób malloc() wie, gdzie zaczyna się hałda?

+0

Może to być zakodowane na stałe. –

+4

Wyobrażam sobie, że będzie to zależne od platformy.Czy chcesz uzyskać odpowiedź na konkretną platformę? –

+1

możliwy duplikat [Jak działają malloc() i free()?] (Http://stackoverflow.com/questions/1119134/how-do-malloc-and-free-work) – ControlAltDel

Odpowiedz

9

malloc implementacje zależą od systemu operacyjnego; jest to proces, którego używają, aby uzyskać początek sterty. W systemie UNIX można to osiągnąć, wywołując sbrk(0) w czasie inicjalizacji. W innych systemach operacyjnych proces jest inny.

Pamiętaj, że możesz wdrożyć malloc bez znajomości położenia sterty. Możesz zainicjować bezpłatną listę na NULL i wywołać sbrk lub podobną funkcję z rozmiarem alokacji za każdym razem, gdy nie zostanie znaleziony wolny element o odpowiednim rozmiarze.

+0

Ahah, światło włącza się. Właśnie tego szukałem. – mclaassen

+0

Inna wspomniana odpowiedź była myląca z powodu tego wiersza "Wywołanie systemowe sbrk przesuwa" granicę "segmentu danych." I z mojego rozumienia segmentu danych zapisuje dane globalne. Tak więc założyłem, że kupa musi znajdować się na końcu segmentu danych, ale nie rozumiem, w jaki sposób malloc() mógł wiedzieć, gdzie był koniec. – mclaassen

0

W systemie Windows używa się Heap functions do pobierania pamięci sterty procesowej. Środowisko wykonawcze C przydzieli bloki pamięci na stercie za pomocą HeapAlloc, a następnie użyje go do spełnienia żądań malloc.

2

To tylko o implementacje Linuksa malloc

Wiele malloc implementacji w systemie Linux lub POSIX użyć mmap(2) syscall trochę dość duży zakres pamięci. następnie mogą użyć munmap(2), aby je zwolnić.

(Wygląda sbrk(2) nie może być używany wiele dłużej; w szczególności nie jest ASLR przyjazny i może nie być wielowątkowego przyjazną)

Oba te syscalli może być dość ekspansywny, tak niektóre implementacje wymagają pamięci (używając mmap) w dość dużych porcjach (np. w kawałku jednego lub kilku megabajtów). Następnie zarządzają wolną przestrzenią, np. powiązane listy bloków itp. Będą obsługiwać różne małe mallocs i duże mallocs.

mmap syscall zwykle nie rozpocząć podając zakres pamięci w pewnych stałych elementów (w szczególności z powodu ASLR

Spróbuj w systemie uruchomić prosty program drukowania wynik pojedynczy malloc (EG 128 int. - s). prawdopodobnie będzie obserwować różne adresy z jednego biegu na drugi (z powodu ASLR). i strace(1) -ing jest bardzo pouczająca. Spróbuj również cat /proc/self/maps (lub wydrukować linie /proc/self/maps wewnątrz programu). Patrz proc(5)

Więc nie ma potrzeby "zaczynać" th e sterty pod jakimś adresem i na wielu systemach, które nie mają żadnego sensu. Jądro podaje segmenty wirtualnych adresów na losowych stronach.

BTW, zarówno GNU libc i musl libcfree software. Powinieneś zajrzeć do kodu źródłowego swojej implementacji malloc. Uważam, że source code of musl libc jest bardzo czytelny.

Powiązane problemy