malloc() によって返されるストレージはそうではありません ゼロ初期化。そうだと思い込まないでください。
あなたのテスト プログラムでは、それはただのまぐれです:malloc()
mmap()
から新しいブロックを取得しました 、しかしそれに頼らないでください。
たとえば、あなたのプログラムを私のマシンでこのように実行すると:
$ echo 'void __attribute__((constructor)) p(void){
void *b = malloc(4444); memset(b, 4, 4444); free(b);
}' | cc -include stdlib.h -include string.h -xc - -shared -o pollute.so
$ LD_PRELOAD=./pollute.so ./your_program
a at 0x7ffd40d3aa60: 1256994848 21891 1256994464 21891 1087613792 32765 0 0
b at 0x55834c75d010: 67372036 67372036 67372036 67372036 67372036 67372036 67372036 67372036
2 番目の例は、単純に malloc
のアーティファクトを公開することです glibc での実装。 malloc
を繰り返すと /free
8 バイトを超えるバッファを使用すると、次のサンプル コードのように、最初の 8 バイトだけがゼロになっていることが明確にわかります。
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
const size_t n = 4;
const size_t m = 0x10;
int main()
{
for (size_t i = n; i; --i) {
int *const p = malloc(m*sizeof(int));
printf("%p ", p);
for (size_t j = 0; j < m; ++j) {
printf("%d:", p[j]);
++p[j];
printf("%d ", p[j]);
}
free(p);
printf("\n");
}
return 0;
}
出力:
0x55be12864010 0:1 0:1 0:1 0:1 0:1 0:1 0:1 0:1 0:1 0:1 0:1 0:1 0:1 0:1 0:1 0:1
0x55be12864010 0:1 0:1 1:2 1:2 1:2 1:2 1:2 1:2 1:2 1:2 1:2 1:2 1:2 1:2 1:2 1:2
0x55be12864010 0:1 0:1 2:3 2:3 2:3 2:3 2:3 2:3 2:3 2:3 2:3 2:3 2:3 2:3 2:3 2:3
0x55be12864010 0:1 0:1 3:4 3:4 3:4 3:4 3:4 3:4 3:4 3:4 3:4 3:4 3:4 3:4 3:4 3:4
スタックがどのように初期化されても、C ライブラリは main
を呼び出す前に多くの処理を行うため、元のスタックは表示されません。 、そしてそれらはスタックに触れます。
GNU C ライブラリを使用すると、x86-64 では、_start エントリ ポイントで実行が開始され、__libc_start_main
が呼び出されます。 物事をセットアップするために、後者は main
を呼び出すことになります . main
を呼び出す前に 、他の多くの関数を呼び出し、さまざまなデータがスタックに書き込まれます。スタックの内容は関数呼び出し間でクリアされないため、main
に入ると 、スタックには以前の関数呼び出しの残り物が含まれています。
これは、スタックから取得した結果のみを説明しています。一般的なアプローチと仮定に関する他の回答を参照してください。
どちらの場合も、初期化されていません その内容について推測することはできません。
OS がプロセスに新しいページを割り当てる必要がある場合 (それがスタック用か、malloc()
によって使用されるアリーナ用か) )、他のプロセスからのデータを公開しないことを保証します。それを確実にする通常の方法は、それをゼロで埋めることです(ただし、 /dev/urandom
のページを含む、他のもので上書きすることも同様に有効です - 実際、いくつかのデバッグ malloc()
実装は、ゼロ以外のパターンを記述して、あなたのような誤った仮定をキャッチします)。
malloc()
の場合 すでに使用され、このプロセスによって解放されたメモリからの要求を満たすことができる場合、その内容はクリアされません (実際、クリアは malloc()
とは関係ありません) それはできません-メモリがアドレス空間にマップされる前に発生する必要があります)。プロセス/プログラムによって以前に書き込まれたメモリを取得する場合があります (例:main()
より前) ).
サンプル プログラムでは、malloc()
が表示されています。 このプロセスによってまだ書き込まれていない領域 (つまり、新しいページからの直接の領域) と、(main()
より前に) 書き込まれたスタック プログラムのコード)。スタックをさらに調べると、(成長の方向で) さらに下にゼロが埋め込まれていることがわかります。
OS レベルで何が起こっているかを本当に理解したい場合は、C ライブラリ レイヤーをバイパスし、brk()
などのシステム コールを使用して対話することをお勧めします。 と mmap()