[解決済み] なぜgccのmallocは値を0に初期化するのですか?
質問
プラットフォームによって違うかもしれませんが
gccでコンパイルして以下のコードを実行すると、私のubuntu 11.10では毎回0が表示されます。
#include <stdio.h>
#include <stdlib.h>
int main()
{
double *a = malloc(sizeof(double)*100)
printf("%f", *a);
}
callocがあるのに、mallocはなぜこのような挙動をするのでしょうか?
たまにならいいのに、値を0に初期化するだけで、不要なパフォーマンスオーバーヘッドが発生するということはないのでしょうか?
EDIT: ああ、私の前の例は initiazling ではなく、たまたま "fresh" ブロックを使用しました。
私が正確に探していたのは、なぜ大きなブロックを割り当てるときにそれを初期化するのかということです。
int main()
{
int *a = malloc(sizeof(int)*200000);
a[10] = 3;
printf("%d", *(a+10));
free(a);
a = malloc(sizeof(double)*200000);
printf("%d", *(a+10));
}
OUTPUT: 3
0 (initialized)
しかし、mallocするときにsecurityの理由があることを指摘してくれてありがとうございます! (考えたこともありませんでしたが)。確かに、新しいブロックやラージブロックを割り当てるときは0に初期化する必要がありますね。
どのように解決するのですか?
簡単な答えです。
そうではなく、あなたの場合、たまたまゼロになっただけです。
(また、あなたのテストケースでは、データがゼロであることは表示されません。1つの要素がゼロであるかどうかを示しているだけです)。
長い回答です。
を呼び出すと
malloc()
を呼び出すと、2つのうちの1つが起こります。
- 同じプロセスから以前に割り当てられ、解放されたメモリを再利用します。
- オペレーティングシステムから新しいページを要求します。
最初のケースでは、メモリは以前の割り当てから残ったデータを含んでいます。そのため、メモリはゼロにはなりません。これは、小さな割り当てを実行するときの通常のケースです。
2 番目のケースでは、メモリは OS からのものです。これは、プログラムがメモリを使い果たしたとき、または非常に大きな割り当てを要求しているときに起こります。(あなたの例のような場合)
これがキャッチです。 OS から送られてくるメモリは セキュリティ の理由でゼロになります。
OSがメモリを与えるとき、そのメモリは別のプロセスから解放されている可能性があります。そのため、そのメモリにはパスワードのような機密情報が含まれている可能性があります。そこで、そのようなデータを読み取られないようにするために、OSはメモリを渡す前にゼロにするのです。
*C標準はこれに関して何も言っていないことに注意してください。これは厳密には OS の動作です。したがって、このゼロ化は、セキュリティが懸念されないシステムでは存在するかもしれませんし、存在しないかもしれません。
もっとパフォーマンスの背景を説明するために
コメントで@R.が言及しているように、このゼロ化によって、常に
を使う
calloc()
の代わりに
malloc()
+
memset()
.
calloc()
はこの事実を利用することで、個別の
memset()
.
一方、このゼロ化がパフォーマンスのボトルネックになることもあります。いくつかの数値的なアプリケーション (たとえば アウトオブプレース FFT のような)数値計算アプリケーションでは、スクラッチメモリの巨大な塊を割り当てる必要があります。それを使ってどんなアルゴリズムでも実行し、それから解放します。
これらのケースでは、ゼロ化は不要であり、純粋なオーバーヘッドに相当します。
私が見た最も極端な例は、48 GB のスクラッチ バッファで 70 秒の操作のために 20 秒のゼロ化オーバーヘッドです。(おおよそ 30% のオーバーヘッド)。 (許可: そのマシンにはメモリ帯域幅の不足がありました)。
明らかな解決策は、単にメモリを手動で再利用することです。しかし、それにはしばしば確立されたインターフェイスを突破する必要があります。(特にそれがライブラリルーチンの一部である場合)
関連
-
[解決済み】ENOENTが「そのようなファイルやディレクトリはありません」という意味であるのはなぜですか?
-
[解決済み] mallocの結果はキャストするのですか?
-
[解決済み] なぜGCCはa*a*a*a*aを(a*a*a)*(a*a*a)に最適化しないのでしょうか?
-
[解決済み] C言語では「?」演算子は何をするのですか?
-
[解決済み] 配列の場合、なぜ a[5] == 5[a] になるのでしょうか?
-
[解決済み] 配列のすべてのメンバーを同じ値で初期化するには?
-
[解決済み] Cプリプロセッサはなぜ "linux "という単語を定数 "1 "と解釈するのですか?
-
[解決済み] g++とgccの違いは何ですか?
-
[解決済み] アセンブリがCより速いのはどんなとき?[クローズド]
-
[解決済み】malloc+memsetはcallocより遅いのはなぜ?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
C 言語のポインタ配列のポインタ型、ポインタに値を割り当てるために配列名を使用、コンパイル時の警告:互換性のないポインタ型からの初期化
-
[解決済み] Valgrind が初期化されていないバイトについて警告する
-
[解決済み] なぜmemsetではなくbzeroを使用するのですか?
-
[解決済み] C関数から文字列を返す
-
[解決済み] C言語で関数型プログラミングを行うためのツールにはどのようなものがありますか?
-
[解決済み] mallocの結果はキャストするのですか?
-
[解決済み] mallocとcallocの違い?
-
[解決済み] 講師が書いたC言語のファイルは、なぜ最初の行に#が一つ付いているのですか?
-
[解決済み] C言語で "unsigned long "をprintfする方法は?
-
[解決済み】malloc+memsetはcallocより遅いのはなぜ?