pokud mám pole přidělené na zásobníku, ukazatel na první prvek bude mít také nižší> hodnotu než ukazatel na druhý prvek?
Není důležité „jak“ pole alokujete, můžete zvýšit nebo snížit ukazatel zásobníku, ale ve výsledku máte pro pole vyhrazený adresní prostor.
Dá se s nimi normálně pracovat, protože nejnižší adresa je vyhrazena pro prvek 0.
takže moje otázka zní, jaké je správné rozložení paměti pro proces v Linuxu?
Můžete si to ověřit sami. Vložte někam do svého programu něco jako std::cin.get()
pro pozastavení programu.
Poté spusťte v samostatném prostředí:
ps aux | grep your_program_name
cat /proc/<pid show by grep>/maps
Tím se vytisknou mapování paměti vašeho procesu, kde můžete vidět, kde je v paměti umístěna halda, zásobník a další věci.
O zásobníku:předpokládejme, že máte obyčejný stroj s Linuxem a 64bitovým CPU Intel nebo AMD. Poté napište následující kód:
extern void f(int);
void g(int param)
{
f(param);
}
zkompilovat a rozebrat:
g++ -ggdb -c test_my_stack.cc && objdump -S test_my_stack.o
můžete vidět (nedůležité detaily odstraněny):
void g(int param)
{
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 83 ec 10 sub $0x10,%rsp
8: 89 7d fc mov %edi,-0x4(%rbp)
f(param);
b: 8b 45 fc mov -0x4(%rbp),%eax
jak můžete vidět v sub $0x10,%rsp
rezervovali jsme místo v zásobníku zmenšením (posunutím dolů) ukazatele zásobníku.
První věc, která mě s tímto obrázkem obtěžovala, je, že pokud halda rostla z vysoké na nízkou, pak kdybych alokoval pole na haldě, neměl by mít ukazatel na druhý prvek hodnotu int menší než ukazatel na první prvek? což by bylo matoucí
Vůbec ne. Řekněme, že alokujete pole 10 bajtů z fondu paměti, který roste od vysoké k nízké. Vše, co by alokátor musel udělat, je snížit „spodní část“ tohoto fondu paměti o 10 a pak použít tuto hodnotu jako začátek přiděleného pole. Pole by pak končilo na starém „dole“. Aritmetika ukazatele by stále fungovala podle očekávání, ale „rostli byste“ směrem k nízké adrese.