• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Jaki obiekt gdzie jest przechowywany?

+4 głosów
6,117 wizyt
pytanie zadane 17 kwietnia 2015 w C i C++ przez Sebastian Fojcik Nałogowiec (43,040 p.)

Program może mieć przydzielone 2 rodzaje pamięci: stos i stertę.
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ę)

Proszę mnie upewnić, czy poniższe zapisy są prawdziwe:

Obiekty automatyczne (lokalne) ---> stos (śmieci)
Obiekty tymczasowe ---> stos
Obiekty statyczne---> sterta (inicjalizowane 0)
Obiekty globalne ---> sterta (inicjalizowane 0)
Obiekty dynamiczne ---> sterta (śmieci)

Pozdrawiam społeczność.

1 odpowiedź

+1 głos
odpowiedź 17 kwietnia 2015 przez achilles147 Dyskutant (9,580 p.)
wybrane 8 lutego 2016 przez Sebastian Fojcik
 
Najlepsza
przeanalizuj sobie ten mały programik

#include "stdafx.h"
#include <iostream>

using namespace std;

int g=1; //globalna
int h=1; //globalna
int _tmain(int argc, _TCHAR* argv[])
{
	int a=10; //lokalna
	int b=10; //lokalna
	int* c=new int(1);  //sterta
	int* d =new int(1); //sterta
	static int e=1; //statyczna
	static int f=1; //statyczna

	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;
}

 

komentarz 17 kwietnia 2015 przez achilles147 Dyskutant (9,580 p.)
zastanow się nad pewnymi podobieństwami w obrszarach pamięci jak jeszcze będzie coś nie jasne to pisz!
komentarz 17 kwietnia 2015 przez Sebastian Fojcik Nałogowiec (43,040 p.)
Z analizy Twojego programu wywnioskowałem, że automatyczne ze stosu są gdzieś, dynamiczne ze sterty są gdzieś indziej, a statyczne i globalne są zakładane obok siebie (czyli w tym samym miejscu), ale znowuż gdzieś indziej niż stos i sterta.

Czytałem gdzieś właśnie, że sterta jest dla dynamicznej alokacji, ale w takim razie potrzebuję jeszcze odpowiedzi na pytania:

Jak wiadomo stos łatwo przepełnić. Wewnątrz funkcji main() wystarczy int tab[500000]; i mamy "stack overflow", ale przy zakładaniu identycznej tablicy w zakresie globalnym nie ma błędu. To znaczy, że globalne (i statyczne) nie są zakładane na stosie.

automatyczne ---> stos
dynamiczne ---> sterta
globalne i statyczne ---> ???? <--- na to szukam jeszcze odpowiedzi
komentarz 17 kwietnia 2015 przez achilles147 Dyskutant (9,580 p.)
globalne i zmienne statyczne są alokowane w obszarze pamięci statycznej. Nie jest to Stos ani nie jest to sterta. Tak naprawdę między globalną zmienna a statyczną nie ma dużej różnicy. Statyczna zmienna to taka zmienna globalna którą możemy stworzyć wewnątrz jakiejś funkcji.
komentarz 17 kwietnia 2015 przez Sebastian Fojcik Nałogowiec (43,040 p.)

Podsumuję to rysunkiem: (pamięć operacyjna = RAM + pamięć wirtualna)Jeszcze tylko ostatnia rzecz:

Obszar pamięci statycznej jest stały, zarezerwowany na starcie programu i jest OK.
A gdy próbuję tablicę 500000 elementową 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:

Dlaczego kompilator ustala, że jest taki rozmiar stosu i już?
Dlaczego statycznych nie obowiązuje limit tak jak stosu?
Czy ten stos jest jakiś szybszy od sterty? No bo przecież RAM to RAM.

Problem mam teraz tylko jeden, ale zadaję dużo pytań, aby otrzymać jak najdokładniejszą odpowiedź. Pozdrawiam i dobranoc :)

komentarz 30 listopada 2017 przez Marcin Ziajkowski Nowicjusz (100 p.)
Z twojego opisu wynika że pamięć na obiekty czy zmienne statyczne jest stała. Mam rozumieć że podczas pracy programu pamięć ta się nie zwiększa?

Dlaczego pytam, mam jedne teoretyczne pytanie. Co by się stało jeżeli stworzylibyśmy klasę w której jest pole statyczne. A w czasie pracy programu dynamicznie tworzyli nowe instancje tej klasy.

Żeby to bardziej zwizualizować, To klasa nazywa się Mebel. W programie do projektowania mieszkania, dodajemy nowe meble (Krzesła, tapczany, stoły, kanapy) i ustawiamy je w mieszkaniu. Każdy z tych mebli ma inne statyczne ID.

Skoro tworzymy dynamiczną ilość mebli to skąd kompilator wie ile pamięci statycznej zadeklarować?
komentarz 1 grudnia 2017 przez Sebastian Fojcik Nałogowiec (43,040 p.)

Witaj,

nie wiem czy do końca rozumiesz jak działa statyczny składnik klasy. Jest on tworzony tylko raz i jest wspólny dla wszystkich obiektów klasy, więc dodanie nowego obiektu (dynamicznie) nie spowoduje dodania nowej zmiennej statycznej. Jeśli każdy z mebli miałby statyczne ID, to wszystkie meble miałyby jedno, wspólne ID.

Spójrz na przykład:

class Klasa
{
public:
	static int statyczna;
};

int Klasa::statyczna = 5;

int main()
{
	cout << Klasa::statyczna << endl; // wypisze 5
	Klasa obiekt1;
	cout << obiekt1.statyczna << endl; // wypisze 5
	obiekt1.statyczna = 10;
	cout << Klasa::statyczna << endl;	// wypisze 10
	Klasa obiekt2; 
	cout << obiekt2.statyczna << endl;	// wypisze 10

	return 0;
}

Jak widać, zmienna statyczna jest wspólna dla wszystkich obiektów klasy. Pokazałem też wyżej, że mogę się do niej odwoływać po samej nazwie klasy, bez żadnego obiektu.

Statyczne składniki klas są tworzone w obszarze pamięci statycznej tak samo jak zwykłe (globalne) zmienne statyczne. (teoretycznie zmienna globalna i statyczna klasy nie różnią się prawie niczym. Obydwie widoczne są w całym pliku, a ich zasięg można przedłużać za pomocą słowa kluczowego extern)

Spójrz na przykład:

class Klasa
{
public:
	static int statycznaKlasy;
};

int Klasa::statycznaKlasy = 5;
static int statycznaZwykla = 10;

int main()
{
	cout << (int)&Klasa::statycznaKlasy << endl; // wypisze 20037684
	cout << (int)&statycznaZwykla << endl; // wypisze 20037688

	return 0;
}

(takie adresy wypisuje mój komputer, u Ciebie będzie inaczej)
Więc jak widzisz statyczna klasy jest zwykłą statyczną. Obie zmienne znajdują się w pamięci obok siebie. (obszar pamięci statycznej). Zauważ, że nie utworzyłem nawet żadnego obiektu w programie, a moja klasa już ma zmienną statyczną.

Jeśli chodzi o pozostałe składniki klasy (niestatyczne), to znajdują się one tam gdzie instancja (obiekt) klasy. Czyli jeśli utworzysz obiekt Klasa obiekt; wewnątrz funkcji np. main, to wszystkie składowe klasy będą na stosie, jeśli utworzysz obiekt klasy operatorem new, to będą na stercie, jak obiekt zrobisz poza funkcją globalnie, to wszystkie składniki klasy będą w obszarze pamięci statycznej itd.

Istotną rzeczą jest to, że składniki klasy będą ulokowane obok siebie. Być może przewrócę Ci teraz świat do góry nogami, ale klasy (class) podobnie jak struktury (struct) są trochę jak tablice, które przechowują różne zmienne. Jak pewnie pamiętasz przy tablicach była taka święta formułka "Nazwa tablicy jest adresem jej pierwszego elementu". W przypadku klas jest tak samo! Przykład:

class Klasa
{
public:
	int zmienna1 = 1;
	int zmienna2 = 2;
	int zmienna3 = 3;
};

int main()
{
	Klasa obiekt;
	cout << (int)&obiekt << endl; // wypisze 4192540
	cout << (int)&obiekt.zmienna1 << endl; // 4192540
	cout << (int)&obiekt.zmienna2 << endl; // 4192544
	cout << (int)&obiekt.zmienna3 << endl; // 4192548

	return 0;
}

Jak widzisz adres obiektu jest taki sam jak adres pierwszej jej zmiennej składowej. Jakbyś rzutował obiekt obiekt na wskaźnik int*, to mógłbyś się posługiwać obiektem klasy jak tablicą ;-) Kolejne zmienne składowe stoją obok siebie i różnią się o 4 bajty (bo int).

Podsumowując Twoje pytanie. Instancje (obiekty) klasy są przechowywane tak jak zwykłe zmienne, czyli w zależności gdzie i jak je utworzysz. Wszystkie składniki klasy (poza statycznymi) są przechowywane razem, obok siebie, jak tablica.

Statyczne składniki klasy są przechowywane w obszarze pamięci statycznej, który jest rezerwowany (praktycznie tak jak dynamiczna pamięć przy pomocy new) przy starcie programu. Kompilator wie ile wziąć pamięci, bo statycznych/globalnych zmiennych nie da się tworzyć w trakcie działania programu.

Jakbyś miał jeszcze jakieś pytania, to pisz. Z chęcią na nie odpowiem :-)

Podobne pytania

0 głosów
0 odpowiedzi 1,025 wizyt
pytanie zadane 21 lutego 2022 w Systemy operacyjne, programy przez Dorian Bajorek Dyskutant (7,920 p.)
+1 głos
0 odpowiedzi 709 wizyt
pytanie zadane 3 maja 2021 w Systemy operacyjne, programy przez tomasz12345 Użytkownik (750 p.)
+1 głos
2 odpowiedzi 3,078 wizyt

93,720 zapytań

142,648 odpowiedzi

323,266 komentarzy

63,270 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Twierdza Linux. Bezpieczeństwo dla dociekliwych

Aby uzyskać rabat -10%, użyjcie kodu pasja-linux, wpisując go w specjalne pole w koszyku.

...