web-dev-qa-db-ja.com

スタックとヒープのメモリ割り当て

これは非常に基本的な質問のように思えるかもしれませんが、私の頭の中にありました。

ローカル変数を割り当てるとき、それはスタックに入ります。同様に、動的割り当ては、変数をヒープに移動させます。さて、私の質問は、この変数は実際にはスタックまたはヒープ上にあるのか、それともスタックとヒープ内の参照だけなのかです。

例えば、

変数int iを宣言するとします。これで、このiがスタックに割り当てられます。それで、iのアドレスを出力すると、これはスタック上の場所の1つになりますか?ヒープについても同じ質問です。

20
Samir Baid

質問の内容はよくわかりませんが、できる限りお答えします。

次の例では、スタックで変数iを宣言しています。

int i;

&iを使用してアドレスを要求すると、スタック上の実際の場所がわかります。

mallocを使用して動的に何かを割り当てると、実際には[〜#〜] two [〜#〜]のデータが保管。動的メモリはヒープに割り当てられ、ポインタ自体はスタックに割り当てられます。したがって、このコードでは:

int* j = malloc(sizeof(int));

これは、整数用にヒープ上のスペースを割り当てています。また、ポインタ(j)のためにスタック上のスペースを割り当てています。変数jの値は、mallocによって返されるアドレスに設定されます。

48
Chris Eberle

うまくいけば、以下が役に立ちます:

void foo()
{
    // an integer stored on the stack
    int a_stack_integer; 

    // a pointer to integer data, the pointer itself is stored on the stack
    int *a_stack_pointer; 

    // make a_stack_pointer "point" to integer data that's allocated on the heap
    a_stack_pointer = (int*)malloc(10 * sizeof(int));
}

スタック変数の場合、変数自体(実際のデータ)がスタックに格納されます。

ヒープに割り当てられたメモリの場合、基になるデータは常にヒープに格納されます。このメモリ/データへのポインタmayは、スタックにローカルに格納されます。

お役に立てれば。

11
Darren Engwirda

ポインタ変数自体はスタックに常駐します。ポインタが指すメモリはヒープに常駐します。

int *i = malloc(sizeof(int));

iはスタックに常駐し、私が指す実際のメモリは*iはヒープ上にあります。

5
Suroot

クリスに同意します。それを説明するためのちょうど別の方法。次のコードを検討してください。

int* j = malloc(sizeof(int));
free(j);

ヒープからメモリの割り当てを解除する必要があるfree(j)を使用した後でも、ポインタは存在し、明示的にNULLにする必要があります。これは、ポインタの対応するスタックも存在することを明確に示唆しています。それ以外の場合は、freeコマンドの後には存在していなかったはずです。このスタック変数は、mallocを使用してメモリが動的に割り当てられたヒープ上のアドレスを指す変数です。

2
Prateek

エバール氏の答えは100%正解ですが、Googleは_malloc heap or stack_を検索するときにこれを最初の答えとして表示するため、malloc()がヒープにデータを割り当てるのはほとんどの場合です。 。割り当てられたデータが _MMAP_THRESHOLD_ 32ビットシステムでは通常128kbより大きい場合、malloc()しないヒープを使用し、代わりに、通常はスタックの下にあるAnonymous Memory Segmentにデータを割り当て、メモリ不足の方向に拡大する。

これは、動的にロードされるライブラリが配置されている領域と同じです(_libc.so_など)。 _man malloc_ からの関連する部分は次のとおりです。

通常、malloc()はヒープからメモリを割り当て、必要に応じてsbrk(2)を使用してヒープのサイズを調整します。 MMAP_THRESHOLDバイトより大きいメモリブロックを割り当てる場合、glibc malloc()実装は、mmap(2)を使用してメモリをプライベート匿名マッピングとして割り当てます。 MMAP_THRESHOLDはデフォルトで128 kBですが、mallopt(3)を使用して調整できます。 Linux 4.7より前のバージョンでは、mmap(2)を使用して実行される割り当ては、RLIMIT_DATAリソース制限の影響を受けませんでした。 Linux 4.7以降、この制限はmmap(2)を使用して実行される割り当てにも適用されます。

実用的な例として、自由に 次の投稿 を確認してください。基本的にmalloc()で300kbを割り当て、次に_pmap <PID>_を実行して関連するメモリセグメントを表示します。

0
Solidak

スタックまたはヒープは別個のメモリではなく、実行中のプログラムがシステムによって割り当てられるメモリセグメントであり、メモリ内のデータを編成するためのさまざまな方法です。

したがって、&iを取得する場合、それはメモリアドレスであり、そのように単純です。

0
Anh Pham