Tzn, że gdy wyjdę z bloku funkcji, te zmienne i ich wartości nadal są w pamięci? Wiem że tak jest w przypadku pamięci alokowanej na stercie (poprzez malloc/new) ale nie na stosie. Trochę się to kłóci z tym co przeczytałem w "mądrych książkach", tj. że gdy wychodzimy z bloku np. funkcji, wszystkie zmienne lokalne tam są usuwane.
Mądre książki upraszczają mocno. Z drugiej strony, prawdopodobnie nie potrzebujesz tego wiedzieć ;)
Jeśli czujesz się na siłach, obszerne wyjaśnienia są tutaj: http://en.wikipedia.org/wiki/X86_calling_conventions (w szczególności akapit o cdecl)
Skrócona wersja, wymaga trochę wiedzy niekopoziomowej
, ale mam nadzieję że pomoże. No więc tak naprawdę, to wygląda to tak:
Przekazując parametry do funkcji, tak naprawdę są one wrzucane na pewien stos
, z którego funkcja docelowa je czyta. Na szczyt stosu (dzięki czemu wiemy skąd czytać) wskazuje wskaźnik stosu, nazwijmy go ESP.
Teraz załóżmy że masz funkcję
int foo(int a, int b, int c) {
}
I wywołujesz ją jako:
foo(1, 2, 3)
Wygeneruje to taki kod maszynowy:
push 3 ; trzeci argument na stos
push 2 ; drugi argument na stos
push 1 ; pierwszy argument na stos
call foo ; wywołanie funkcji
add esp, 12 ; poprawienie wskaźnika stosu (cofnięcie o 3 parametry do góry: każdy po 4 bajty, razem 3*4=12 bajtów)
Przed wywołaniem foo stos wygląda tak:
[to co było wcześniej na stosie] <- ESP
W momencie wywołania funkcji foo, na stosie będzie coś takeigo:
[to co było wcześniej na stosie]
3 (trzeci argument)
2 (drugi argument)
1 (pierwszy argument)
adres_powrotu (szczegół techniczny) <- ESP
A po tym jak foo skończy się wykonywać, będzie prawdopodobnie wyglądać tak:
[to co było wcześniej na stosie] <- ESP
(trzeci argument)
(drugi argument)
(pierwszy argument)
adres_powrotu (szczegół techniczny)
Argumenty leżą poniżej wskaźnika stosu, czyli są już nieaktualne, ale to nie znaczy że zmienne są niszczone
w jakiś sposób - po prostu siedzą tam aż coś je nadpisze.
Jeśli zwrócisz referencję na trzeci argument, to będzie pokazywać na miejsce w pamięci gdzie siedzi trzeci argument. Nie ma znaczenia że ten argument jest już nieaktualny.
[to co było wcześniej na stosie] <- ESP
(trzeci argument) <- referencja na to miejsce w pamięci
(drugi argument)
(pierwszy argument)
adres_powrotu (szczegół techniczny)
Swoją drogą możesz to łatwo zobaczyć wywołując po zwróceniu referencji inną funkcję - prawdopodobnie wtedy pamięc zostanie już nadpisana.
edit: przy okazji widać na czym polega kopiowanie zmiennych przy wywoływaniu funkcji - na stos wrzucane są po prostu ich obecne wartości