0

この質問はスタックオーバーフローに関するものなので、ここよりもどこで質問するのがよいでしょうか。

UNIX でプログラム (a.out) にメモリがどのように使用されるかを考えると、次のようになります。

| etext | stack, 2mb | heap ->>>

そして、なぜスタックに 2MB の制限があるのか​​、ここ数年疑問に思っていました。メモリ アドレスに 64 ビットがあることを考慮して、次のように割り当ててみませんか。

| MIN_ADDR                                                              MAX_ADDR|
| heap ->>>>                                                 <<<- stack | etext |

MAX_ADDR は 2^64 付近にあり、MIN_ADDR は 2^0 付近にあるため、その間にプログラムが使用できる多くのバイトがありますが、(実際にページを割り当てることによって) カーネルによって必ずしも考慮されるわけではありません。ヒープとスタックはおそらく互いに到達しないため、2MB の制限は必要ありません (代わりに ~1.8446744e+19 バイトの制限があります)。それらが互いに到達するのが怖い場合は、制限を 2^63 または奇妙で膨大な数に設定します。

さらに、ヒープは低から高に成長するため、カーネルはコンテンツを必ずしもシフトする必要なく、(たとえば malloc で割り当てられた) メモリのブロックのサイズを変更できます。

さらに、スタック フレームのサイズは常に何らかの形で固定されています。returnで使用され、 callで作成されたポインター構造全体も変更する必要があるため、サイズを変更する必要はありません。

これを別のスタックオーバーフローの質問に対する回答として読みました:

「私の直感は次のとおりです。スタックは、ヒープほど管理が容易ではありません。スタックは、連続したメモリ位置に格納する必要があります。つまり、必要に応じてスタックをランダムに割り当てることはできませんが、少なくとも仮想を予約する必要があります。予約された仮想アドレス空間のサイズが大きいほど、作成できるスレッドは少なくなります。」

出典: Linux (x86) のページ サイズが 4 KB である理由、その計算方法

しかし、大量のメモリ アドレスがあります。したがって、これは意味がありません。では、なぜ 2MB なのか?

私が尋ねる理由は、スタックにメモリを割り当てることは、ダングリング ポインターとメモリ リークに関して非常に安全だからです。

たとえば、私は好きです

int foo[5];

それ以外の

int *foo = malloc(5*sizeof(int));

それ自体で割り当てが解除されるためです。また、スタック上での割り当ては、malloc による割り当てよりも高速です。ただし、スタックに画像 (つまり、jpeg または png) を割り当てると、スタックがオーバーフローする危険なゾーンにいます。

この問題に関する別のポイント、これも許可しないのはなぜですか:

int *huge_list_of_data = malloc(1000*sizeof(char), 10 000 000 000*sizeof(char))

ここで、最初は 1KB のサイズのリスト オブジェクトを割り当てますが、配置されたページが他の目的で使用されないようにカーネルに割り当てるように要求し、その背後に 10GB のページを保持する必要があります。必要に応じて(部分的に)交換できます。

この方法では、10 GB のメモリは必要なく、10 GB のメモリアドレスのみが必要です。

では、なぜいいえ:

void *malloc( unsigned long, unsigned long );

?

要するに、メモリ割り当ての問題を解決するために UNIX のページング システムを使用しないのはなぜでしょうか。

読んでくれてありがとう。

4

0 に答える 0