Segmenty pamięci programu
Pamięć działającego programu podzielona jest na segmenty. Podział na segmenty jest dobrze zobrazowany przez rysunek z wikipedii.
Po kompilacji programu ustalana jest zawartość segmentów text
, data
oraz bss
.
text
- kod źródłowy programu, zwykle jest to obszar tylko do odczytu,data
- zainicjalizowane zmienne globalne,bss
- niezainicjalizowane zmienne globalne.
Podczas działania program korzysta z dwóch dodatkowych segmentów stack
oraz heap
.
stack
- stos wywołań funkcji programu. Jeśli wywołamy w naszym programie jakąś funkcję, to tutaj będą dodane argumenty dla tej funkcji oraz jej zmienne lokalne. Po zakończeniu wywołania funkcji te zmienne znikają z pamięci, dlatego próba zwrócenia z funkcji wskaźnika na zmienną lokalną zakończy się niepowodzeniem.heap
- sterta zawiera wszystkie zmienne, na które pamięć została dynamicznie zaalokowana. Jej zawartość nie jest zwalniana w momencie zdejmowania wywołania funkcji ze stosu.
static
oraz extern
Słowo kluczowe static
może budzić wątpliwości - po co w ogóle go używać, skoro nie umieszczamy danej zmiennej/funkcji w pliku nagłówkowym?
Odpowiedź jest prosta - możemy użyć funkcji/zmiennej z jednego modułu w drugim module bez załączania pliku nagłówkowego - wystarczy zadeklarować istnienie zmiennej/funkcji o danej nazwie, a linker połączy tą deklarację z implementacją za nas.
Tutaj znajduje się dokładniejsze, bardzo sensowne wyjaśnienie tego zjawiska - link.
make:
Przy pisaniu plików makefile
warto pamiętać, że aby dowiedzieć się, czy należy przebudować dany moduł, program make
sprawdza datę edycji jedynie plików wpisanych jako zależności.
Tzn jeśli do pliku źródłowego dodamy nową zależność #include "something.h"
, to załączany moduł należy dodać do zależności w makefile
.