1

私はこの質問について考えてきましたが、まだ説明が見つかりません。

たとえば、C++ プログラムに割り当てるメモリの量を決定するのはどのモジュールですか? コンパイラの推奨を決めるのはOSですか?..リンカ?

また、割り当てられたメモリのスタックとヒープの比率は?

4

4 に答える 4

3

答えはOSによって異なります。通常、実行可能ファイルには、メインスレッドに必要なスタックサイズが含まれており、リンカーによってそこに配置されます。これは、OS設定によってオーバーライドされる場合があります。OS設定は、1つ以上の方法で、場合によってはユーザーごとに構成できます。一部のOSでは、事前にスタックサイズを指定する必要はなく、使用時にスタックを追加できます(ハード制限に達するか、システムの空きメモリがなくなるまで)。事前にサイズを必要とするものは、最初はメモリではなくアドレススペースのみを割り当て、スタックがそこまで到達した場合にアドレスをメモリにマップする場合があります。

通常、ヒープは事前に割り当てられないため、「スタックとヒープの比率」はありません。プロセスに割り当てられるメモリの合計は、制限される場合と制限されない場合があります。制限されていない場合は、システムリソースが許す限り高くなる可能性があります。または、32ビットシステムでは、使用可能なアドレス空間によって制限される可能性があります。

于 2012-04-24T13:17:27.037 に答える
1

これは、C++ 標準にあるような問題ではありません。コンパイラと OS に依存します。

プログラムが要求するリソースを決定する際に OS が考慮に入れる、リンカが生成する種類の例については、以下を参照してください。

http://en.wikipedia.org/wiki/Executable_and_Linkable_Format#ELF_file_layout

状況によっては、OS からリソースを具体的に要求する API があります。

GNU コンパイラでのコンパイル中に Linux で C++ アプリケーションのスタック サイズを変更する

一部の環境では、OS にクォータと制限を設定するように指示する方法もあります。

https://stackoverflow.com/questions/4983120/limit-memory-usage-for-a-single-linux-process

Windows プロセス (またはユーザー) のメモリ制限を設定する

特定の OS がリソースの使用をどのように管理しているかを実証的に調査したい場合は、ドキュメントを探すのではなく、プロセス モニター ユーティリティを使用すると、よりよく理解できるかもしれません。クローズドソースの OS を使用。

于 2012-04-24T13:21:23.603 に答える
1

プログラムとOSに依存します。通常、起動時には、実行可能ファイル、読み取り専用データを保持するのに十分なメモリのみが割り当てられ、スタックには通常約 4k が割り当てられます。次に、 malloc または new を呼び出してメモリを割り当てると、物理メモリがバックアップすることなく仮想メモリ空​​間が取得されます。これは遅延割り当てと呼ばれ、実際に書き込むときにのみメモリが物理的に割り当てられます。

私が話していることのアイデアを得るために、以下をコンパイルして時間を計ってください。

//justwrites.c
#include <stdlib.h>

int main(int argc, char **argv) {

int *big = calloc(sizeof(int),19531); // number of writes

return 0;
}

// deadbeef.c
#include <stdlib.h>

int main(int argc, char **argv) {

int *big = malloc(sizeof(int)*20000000); // allocate 8 million bytes
// immediately write to each page to simulate all at once allocation
// assuming 4k page size on 32bit machine
for ( int* end = big + 20000000; big < end; big+=1024 ) *big = 0xDEADBEEF ;

return 0;
}

// bigmalloc.c 
#include <stdlib.h>

int main(int argc, char **argv) {
int *big = malloc(sizeof(int)*20000000); // allocate 80 million bytes
return 0;
}
于 2012-04-24T13:22:29.263 に答える
0

少なくとも 32 ビット ウィンドウの場合、各プロセスはアドレス空間、2G ユーザー 2G カーネル (すべてのプロセスで共有) の独自のコピーを取得し、仮想メモリ サブシステムにより、同じ場所にアクセスするプロセスがそのプロセスに適切なデータを取得できるようになります。これは、プログラムが同じエントリ ポイントを持ち、同じ実行可能ファイルを持つ他のプロセスで使用中のデータを踏まずに複数回実行できる方法です。

アプリケーションは引き続き仮想メモリを使い果たし、カーネルは物理メモリ、スワップ領域/ページング ファイルがなくなるまで、そのプロセスにより多くの物理メモリを割り当てます。システム コールを使用して、プロセスが使用できるメモリを制限できます。

スタックとヒープは、ほとんどの場合、利用可能なメモリの反対側に割り当てられるため、スタックは利用可能なメモリの上から下に向かって成長し、ヒープは下から上に向かって成長します (この決定はアーキテクチャによって異なります)。これにより、ヒープを多く必要とするがスタックをあまり必要としないプログラムが、スタックを多く必要とするがヒープをあまり必要としないプログラムと同じプランを使用できるように、それらを別々に成長させることができます。

于 2012-04-24T13:25:31.817 に答える