スタックに割り当てられた配列がある場合、最初の要素へのポインターも 2 番目の要素へのポインターよりも値が低くなりますか?
配列を「どのように」割り当てるかは重要ではありません。スタック ポインターを増減できますが、その結果、配列用にアドレス空間が確保されます。
最小アドレスは要素 0 用に予約されているため、通常の方法でそれらを操作できます。
<ブロック引用>だから私の質問は、Linux のプロセスの正しいメモリ レイアウトは何ですか?
自分で確認できます。プログラムのどこかに std::cin.get()
のようなものを挿入します プログラムを一時停止します。
次に、別のシェルで実行します:
ps aux | grep your_program_name
cat /proc/<pid show by grep>/maps
これにより、プロセスのメモリ マッピングが出力され、ヒープ、スタック、およびその他のものがメモリ内のどこに配置されているかを確認できます。
スタックについて:Linux と Intel または AMD 64 ビット CPU を搭載した通常のマシンがあると仮定しましょう。次に、次のコードを記述します:
extern void f(int);
void g(int param)
{
f(param);
}
コンパイルして逆アセンブルします:
g++ -ggdb -c test_my_stack.cc && objdump -S test_my_stack.o
ご覧いただけます (重要でない詳細は削除されています):
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
sub $0x10,%rsp
でわかるように スタック ポインターを減らす (下に移動する) ことで、スタック内のスペースを予約しました。
<ブロック引用>
そのイメージで私を悩ませた最初のことは、ヒープが高から低に成長した場合、ヒープに配列を割り当てた場合、2 番目の要素へのポインターは最初の要素へのポインターよりも int 値が小さくならないことです。混乱するでしょう
全くない。高から低へと成長するメモリのプールから 10 バイトの配列を割り当てるとします。アロケータがしなければならないことは、そのメモリ プールの「底」を 10 減らし、その値を割り当てられた配列の開始点として使用することだけです。配列は、古い「下」で終了します。ポインター演算は期待どおりに機能しますが、下位アドレスに向かって「成長」します。