12

スタック領域でのランタイムメモリ割り当てと、ヒープ領域でのランタイムメモリ割り当てとの違いについて知りたいです。

ライブラリ関数を使用してメモリがどのように割り当てられるかを知っています。

#include<alloca.h> void *alloca(size_t size); //(for runtime memory on stack)

#include<stdlib.h> void *malloc(size_t size); //(for run time memory on heap)

また、alloca関数を使用している場合、スタックに関連付けられているため、そのメモリを明示的に解放する必要はなく、自動的に解放されることも知っています。

どのシステムコールがallocとmallocに関連付けられているか、およびそれらが両方でどのように機能するかを知りたいです。

4

3 に答える 3

13

つまり、使用可能なメモリが不足しない限り、通常はシステムコールを使用しません。

どちらも動作が違うので、説明も違います。

malloc

最初に、プログラムに1MB(たとえば)の割り当て可能なメモリがあるとしましょう。mallocは、この1MBを取得し、割り当てたいメモリを調べ、1MBの一部を切り取って、それを提供する(標準)ライブラリ関数です。簿記のために、それは未割り当ての記憶のリンクリストを保持します。次に、このfree関数は解放されているブロックを解放リストfreeに追加し、メモリを効果的に解放します(ただし、メモリが多すぎると判断して実際にOSに戻す場合を除いて、OSはそれを取得しません。)。

1MBが不足した場合にのみ、malloc実際にオペレーティングシステムにメモリの追加を要求します。システムコール自体はプラットフォームに依存します。たとえば、この回答を見ることができます。

アロカ

これは標準の関数ではなく、さまざまな方法で実装できますが、システム関数を呼び出すことはおそらくありません(スタックサイズを増やすのに十分な機能がある場合を除きますが、わかりません)。

alloca(または同等に(C99)標準可変長配列(VLA)が行うこと)は、適切なレジスター(たとえば、x86)を調整することにより、現在の関数のスタックフレームを増やすことですesp。たまたま同じスタックフレーム上にあるが、可変長配列(またはallocaedメモリ)の後にある変数ebp + size_of_vla + constantは、古き良きシンプルの代わりにアドレス指定されますebp + constant

スタックポインタは、関数が戻ったとき(または通常は任意の{}ブロックが終了したとき)に前の関数のフレームに復元されるため、スタックメモリallocaが自動的に解放されます。

于 2013-03-26T14:57:05.200 に答える
3

このalloca()関数は通常、コンパイラベンダーによって実装され、「システムコール」である必要はまったくありません。

ローカルスタックフレームにスペースを割り当てるだけなので、非常に簡単に実装でき、に比べて非常に高速malloc()です。

Linuxのマニュアルページには次のように書かれています。

インライン化されたコードは、多くの場合、スタックポインタを調整する単一の命令で構成され、スタックオーバーフローをチェックしません。

また、呼び出した関数がalloca()終了すると、メモリが「自動的に」割り当て解除されることに気付いているかどうかはわかりません。alloca()これは非常に重要です。長期的な割り当てを行うために使用することはできません。

于 2013-03-26T14:50:08.533 に答える
0

このalloca関数は、そのマンページによれば、インライン化され、コンパイラによって特別に処理され、拡張される関数です(少なくともgcc)。
動作は実装によって定義されているため、使用しないでください。常に同じように動作することを保証することはできません。

于 2013-03-26T14:48:51.440 に答える