Kyriet Temat założony przez niniejszego użytkownika |
Gdzie są przechowywane jakie obiekty? » 2015-04-19 14:28:14 Bez zbędnych wstępów. Proszę zweryfikować, czy dobrze rozumiem. Program może mieć przydzielone 3 obszary pamięci: stos, stertę i obszar pamięci statycznej. Program może mieć następujące rodzaje obiektów: automatyczne (lokalne), statyczne, globalne, dynamiczne i tymczasowe (do przekazywania funkcji argumentów przez wartość, zwracanie wartości przez funkcję) Obiekty automatyczne (lokalne) ---> stos (śmieci) Obiekty tymczasowe ---> stos Obiekty statyczne---> obszar pamięci statycznej (inicjalizowane 0) Obiekty globalne ---> obszar pamięci statycznej (inicjalizowane 0) Obiekty dynamiczne ---> sterta (śmieci) Do tego dorzucam zrobiony przez siebie obrazek: http://forum.miroslawzelent.pl/?qa=blob&qa_blobid=13018402523810798412Jeśli powyższe zapisy są poprawne, to nie jestem w stanie zrozumieć zachowania kompilatora w tej kwestii: Obszar pamięci statycznej jest stały, rezerwowany na starcie programu i jest OK. (rezerwacja tablicy miliona int'ów jest OK) A gdy próbuję tablicę miliona int'ów zrobić wewnątrz funkcji, to wyrzuca stack overflow. Przecież kompilator widzi, że będę taką tablicę tworzył. Dlaczego nie postępuje tak jak ze statycznymi, czyli nie rezerwuje pamięci ile potrzeba?. Rozumiem, gdyby był to stos na procesorze, gdzie liczy się każdy bajt i byłby limit, ale przecież sterta i stos siedzą w tym samym miejscu (pamięć operacyjna: RAM), więc: 1. Dlaczego kompilator ustala, że jest dany rozmiar stosu i koniec kropka? Co mu szkodzi go powiększyć? 2. Dlaczego obiektów statycznych nie obowiązuje limit tak jak stosu? Robiąc tablicę miliona int'ów tyle właśnie rezerwowanej jest pamięci. (stos jest przy tym upośledzony) 3. Czy ten stos jest jakiś szybszy od sterty? No bo przecież RAM to RAM. Słowem: nie rozumiem po co na obiekty automatyczne nakładany jest ten limit ile mogą maksymalnie miejsca zająć. Pozdrawiam serdecznie społeczność. |
|
pekfos |
» 2015-04-19 16:09:04 Dlaczego kompilator ustala, że jest dany rozmiar stosu i koniec kropka? Co mu szkodzi go powiększyć? |
A skąd wiesz, że za stosem jest nieograniczone wolne miejsce? Adresy związane ze stosem są w zbyt wielu miejscach, by sobie go ot tak przenieść. Dlaczego obiektów statycznych nie obowiązuje limit tak jak stosu? |
Bo jest z góry znany rozmiar? Czy ten stos jest jakiś szybszy od sterty? |
Jest szybszy. |
|
Kyriet Temat założony przez niniejszego użytkownika |
» 2015-04-19 16:23:41 Nie chodziło mi o to, aby go w trakcie działania programu powiększyć. Bo testując taki program: #include <iostream>
using namespace std;
int g = 1; int h = 1; int main() { int a = 10; int b = 10; int * c = new int( 1 ); int * d = new int( 1 ); static int e = 1; static int f = 1; cout << "stos a : " <<& a << endl; cout << "stos b : " <<& b << endl; cout << "sterta c : " <<&( * c ) << endl; cout << "sterta d : " <<&( * d ) << endl; cout << "statyczna e : " <<& e << endl; cout << "statyczna f : " <<& f << endl; cout << "globalna g : " <<& g << endl; cout << "globalna h : " <<& h << endl; system( "PAUSE" ); return 0; }
Widać wyraźnie, że obiekty statyczne i globalne ustawiane są obok siebie, podobnie jak stos. Więc jeśli milion int'ów da się umieścić obok siebie w RAM'ie, obszarze nazwanym "obszar pamięci statycznej", to nie rozumiem, dlaczego nie działa to w przypadku automatycznych obiektów. Ja na ten moment mam takie przekonanie, że tak jak na obrazku, który wyżej zamieściłem, wszystkie te obszary: stos, sterta, obszar pamięci statycznej, to po prostu kawałki RAM'u inaczej nazwane. Dlaczego obiektów statycznych nie obowiązuje limit tak jak stosu? Bo jest z góry znany rozmiar? Obiekty automatyczne też mają znany rozmiar juz w trakcie kompilacji. Jest tablica miliona int'ów i kompilator widzi, że jej nie zmieści, a nie informuje o błędzie. Dlaczego jej nie zmieści? Bo tak sobie ubzdurał, że (przykładowo) 1 MB na stos? I też ciekawe jest to, ze stos jest szybszy od obiektów dynamicznych wskazywanych bezpośrednio wskaźnikami. Obiekty automatyczne i dynamiczne siedzą w RAM'ie (czyt. zarówno stos i sterta to tylko wydzielone obszary RAM), więc jak to możliwe, że do jednych komórek jest szybszy dostęp, a do innych wolniejszy? Chyba że... naszła mnie taka myśl... wierzchołek stosu trzymany jest w rejestrze procesora, ale to dalej nie wyjaśnia "PO CO" kompilator ogranicza jego (stosu) rozmiar. |
|
pekfos |
» 2015-04-19 16:30:22 Obiekty automatyczne też mają znany rozmiar juz w trakcie kompilacji. Jest tablica miliona int'ów i kompilator widzi, że jej nie zmieści, a nie informuje o błędzie |
Nie wie, czy nie zmieści. ale to dalej nie wyjaśnia "PO CO" kompilator ogranicza jego (stosu) rozmiar. |
Musi być ograniczenie. Co za różnica jakie? Jak milion intów przejdzie, to będziesz chciał mieć dwa.. |
|
Kyriet Temat założony przez niniejszego użytkownika |
» 2015-04-19 16:49:43 Chyba coś powoli łapię... Bo przez cały czas zadawałem sobie pytanie: "Dlaczego stos nie działa jak pamięć dynamiczna!!! Dlaczego nie rezerwuje sobie pamięci na potrzebę funkcji, a potem ją zwalnia!". Chyba zrozumiałem. Po co kompilator widząc taką tablicę, miałby z automatu robić stos, aby zmieścić tę tablicę. Nie ma pewności, że ta funkcja zostanie w ogóle wywołana. Nie ma pewności, że nie wywoła samej siebie i potrzeba będzie 2 razy tyle... Więc najlepszym rozwiązaniem jest ustalenie pamięci stosu. Błędnie porównywałem stos do obiektów globalnych i statycznych. A pamięć dla statycznych jest rezerwowana raz, a obiekty automatyczne przy każdym wejściu w zakres lokalny. Więc zmienię podejście i porównam teraz do obiektów dynamicznych: (jestem już bliski ogarnięcia tego, ale jeszcze trochę brakuje) Dlaczego obiekty automatyczne nie zachowują się jak obiekty dynamiczne? To znaczy: Przy każdym wejściu w funkcję rezerwowana jest dla nich pamięć - tak jakby operatorem new . Nie trzeba byłoby wtedy ustalać żadnego ograniczenia. Napisałeś, że stos jest szybszy od sterty (pamięci dynamicznej). Biorąc taką hipotezę, stos ma sens. Ostatnia wątpliwość mi pozostała: Co sprawia, że stos jest szybszy? |
|
pekfos |
» 2015-04-19 18:37:33 Bo alokowanie czegokolwiek na stosie to zwykle operacja na jednej liczbie w rejestrze, a dynamiczna alokacja musi pytać o pamięć system, a ten musi znaleźć jeszcze odpowiednio duże wolne miejsce. Same wywołania to już wielokrotne alokacje na stosie. |
|
Kyriet Temat założony przez niniejszego użytkownika |
» 2015-04-19 18:49:47 To znaczy, że stos, na którym zakładane są obiekty automatyczne, znajduje się w rejestrze procesora? Jeśli tak, to wszystkie moje wątpliwości właśnie zostaną rozwiązane. |
|
pekfos |
» 2015-04-19 18:55:45 To znaczy, że stos, na którym zakładane są obiekty automatyczne, znajduje się w rejestrze procesora? |
Trzeba nie wiedzieć, co to rejestr procesora, by walnąć taką bzdurę.. W 32/64 bitach zmieści się najwyżej adres szczytu stosu i to się tam właśnie znajduje. |
|
« 1 » |