web-dev-qa-db-ja.com

スタックおよびヒープメモリのサイズ

可能性のある複製:
スタックとヒープはどこにありますか?

Cプログラムのメモリレイアウトの基本的な概念に関しては、次のことを理解しています。

  • この言語は、2つの主要なデータ構造stackheapを使用します。
  • スタックは、サブルーチンのローカル変数と簿記データを保存するために作成されます
  • プログラムの動的に割り当てられた変数を格納するためにヒープが作成されます
  • ヒープは本質的に可変長です(スタック上ではあまりわかりません)
  • 通常、実行前にこれらのデータ構造を作成するようにOSに要求するのは、コンパイラ/言語の責任です。

ご質問

  • スタック/ヒープが作成される初期サイズは?誰が決めるの?
  • 物理メモリはどこで作成されますか?一般的な説明は "スタックは最上位アドレスに作成され、ヒープは下位アドレスに作成されます"これを精緻化してください
42
Vivek Maran

「スタックは最上位アドレスに作成され、ヒープは下位アドレスに作成されます」

これは神話です。それは歴史的真実に基づいているかもしれません。実際の生活で見たものと共鳴することがあります。しかし、それは文字通り真実ではありません。

ただし、簡単に探索できます。

#include <stdlib.h>
#include <stdio.h>

void check(int depth) {
    char c;
    char *ptr = malloc(1);
    printf("stack at %p, heap at %p\n", &c, ptr);
    if (depth <= 0) return;
    check(depth-1);
}

int main() {
    check(10);
    return 0;
}

私のマシンで私は見ます:

stack at 0x22ac3b, heap at 0x20010240
stack at 0x22ac0b, heap at 0x200485b0
stack at 0x22abdb, heap at 0x200485c0
stack at 0x22abab, heap at 0x200485d0
stack at 0x22ab7b, heap at 0x200485e0
stack at 0x22ab4b, heap at 0x200485f0
stack at 0x22ab1b, heap at 0x20048600
stack at 0x22aaeb, heap at 0x20048610
stack at 0x22aabb, heap at 0x20048620
stack at 0x22aa8b, heap at 0x20048630
stack at 0x22aa5b, heap at 0x20048640

そのため、スタックは下向きになり、ヒープは上向きになります(神話に基づいて予想されるように)が、スタックのアドレスは小さく、お互いに向かって成長していません(神話は破壊されています)。

ところで、私のcheck関数は末尾再帰であり、一部のコンパイラオプションを使用した実装では、スタックがまったく動かないことがあります。これは、なぜ標準がこのすべての機能を義務付けていないのかを教えてくれます。

58
Steve Jessop

既に述べたように、サイズはOS固有です。たとえばVisual Studioを使用するWindowsでは、デフォルトのスタックサイズは1MBです

msdn

Linuxでは、次のコマンドで現在のコマンドを表示できます。

ulimit -s or -a

Linuxミント64ビットでは、8192 KBと表示されます。

メモリにロードされるプログラムには、いくつかのセグメントがあります。アセンブリでは、.data、.codeなどのプレフィックス(intelx86)を使用してそれらをそれぞれ示すことができます。

それはいくつかのサブセクションを持つデータセグメントです。スタックとヒープの両方は、他のいくつかに加えてその一部です。

スタックは暗黙的に成長することもあります。つまり、別の関数呼び出しを行うと、アクティベーションレコードがスタックにプッシュされ、スタックのメモリをより多く使用します。プログラムが割り当てられたスタックを使い果たすと、無限再帰がクラッシュを引き起こす理由です。

関数呼び出しが戻ると、そのアクティベーションレコードがポップされ、スタックが縮小します。

対照的に、ヒープは反対方向から成長し、動的に割り当てられたすべてのメモリを含みます。

これら2つのセグメントが反対方向に成長する理由は、結合されたメモリの使用率を最大化するためです。コメントで述べたように、これはC標準ではありませんが、ほとんどの一般的なOSにはこれが実装されています。

------スタックが開始されます-----------スタックが下方に成長します

--------互いに交差しない限り、プログラムを実行しても問題ありません。

-------ヒープの開始------------ヒープが上向きに成長する

プログラムがヒープを使用しない場合、スタックもヒープのメモリを含む最大メモリを使用できます。プログラムが再帰呼び出しをほとんど行わず、最小限のローカル変数を使用する(つまり、スタックに使用するメモリが少ない)場合、ヒープを最大限に活用できます。

データセグメントの他の部分はBSSなどで、初期化されていない静的変数などのフィールドが含まれる場合があります

12
fayyazkl

スタック/ヒープが作成される初期サイズは?誰が決めるの?

これはコンパイラーおよびOS固有です。

物理メモリはどこで作成されますか? 「ヒープは最上位アドレスに作成され、下位アドレスにスタックされる」という一般的な説明があります。

これはコンパイラーおよびOS固有です。

本当に。言語標準では、最小スタックサイズは義務付けられておらず、メモリ内のスタックまたはヒープの位置も指定されていません。そしてその理由は、Cプログラムをこれらの詳細に依存せず、したがって異なるプラットフォームに移植しやすくするためです(異なるOS、異なるCPU、異なるコンパイラを読んでください)。

8
Alexey Frunze

まず第一に、C標準はスタック/ヒープがプラットフォームによってどのように実装されるかについての要件を課していません。

What is the initial size with which a stack/heap is created? and who decides it?

通常、プラットフォーム固有のOSによって、プロセスごとにstackの固定サイズが割り当てられます。ヒープサイズに制限はありません。プログラムには通常、使用可能なすべての仮想アドレススペースがあります。

Wherein physical memory are they are created?

これはプラットフォーム固有です。通常、スタックは下向きに成長し、ヒープは上向きに成長します。

3
P.P.