2012-05-24 12 views
6

私はscratchboxのクロスコンパイル環境にいると私は、バイナリを実行すると、私は、プロセスのメモリフットプリントの増加を見ないこのプログラムのメモリフットプリントが増加しないのはなぜですか?

ps -p pid -o cmd,rss,%mem 

を行うと、この

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 

int main() 
{ 
    int * ptr; 
    int i=0; 

    while(1) 
    { 
     ptr = (int*)malloc(10485760 * sizeof(int)); 

     if(ptr == NULL) 
     { 
      printf("Could not malloc\n"); 
      exit(1); 
     } 

     else 
     { 
      printf("Malloc done\n"); 
      for (i = 0 ; i <= 10485759 ; i++) 
      { 
       ptr[i] = i ; 
      } 
      sleep (5); 
      continue; 
     } 
    } 
} 

を持っています。何故ですか?

+0

メモリはすべて最初から一度に割り当てられていますか? –

+3

@arasmussen 'while'ループの内部。 –

+0

コンパイラは、あなたがもはやそのポインタにハンドルを持たないことを見ているでしょう(毎回ptrを書き込むため)それとも、1000万回の繰り返しを実行するのに時間がかかりますか? –

答えて

5

おそらく非常に最適化されたでしょう。 gccがそのmalloc関数を知っている最も近代的なシステムでは

は、非エイリアスのポインタを返します。つまり、同じポインタを2回も返すことはなく、他の場所に保存されたポインタを返すことはありません。

私が想像する、これは非常に非常に難しい見つけるが、malloc関数は一度呼び出されて、その戻り値は何度も繰り返して使用されている可能性があります。理由は:

あなたの記憶はデッドストアであることがわかります。つまり、あなたはそれに書き込みますが、それは決して読み込まれません。ポインタはエイリアスされていないことがわかっているため、他の場所から読み込むためにエスケープされていないため、volatileとマークされていません。あなたのforループ自体は/捨てられるかもしれません。

その時点で、同じメモリを何度も繰り返し使用できます。どれだけのgccがmalloc関数について知っているん:私はそれは難しいと考えていることを見つけるなぜ今ここに

はありますか? Mallocは、「私の部屋に青のランダムな色合いを塗る」というグローバルな「回数」を増やすなど、あらゆる種類の副作用を引き起こす可能性があります。それは電話を落とし、それが副作用のないものと仮定するのは本当に奇妙なようです。地獄、 'malloc'は、100回目の呼び出しごとにNULLを返すように実装することができます(おそらく仕様にはあまりないかもしれませんが、誰が言いますか)。

あなたがしていないことは、あなたのためにそれを解放しています。それは、「知ることができる」ことを超え、「許可されていないことをする」という領域にまで広がっています。それは可能性がありますが、あなたは記憶を漏らすことが許されています。

ここでは2つのことが役に立ちます: 1)コンパイル環境:os、コンパイラ、コマンドラインのフラグ。

および2)最終バイナリの分解。 (objdumpまたはコンパイラから)

+0

gccはmallocについてどれくらい知っていますか?_ gccは 'malloc()'に関するすべてのことを知ることができます。なぜならC標準はその関数の動作を指定しているからです。 – mlp

-2

あなたのコンパイラは、それはあなたがそれを使用していないことを認識したときに(あなたのコードの最適化バージョンもmalloc関数をやっ程度取得することを仮定して)割り当てられたメモリを解放することにより、あなたを助けています。あなたはポインタの値をプリントアウトしようとするかもしれません(printf( "0x%x"、ptr);) - 私はあなたが値を繰り返していると思われます。より信頼性の高いチェックは、既知のビットストリングをメモリに書き込んだり、割り当てられたメモリに既にその文字列が含まれているかどうかを調べています。言い換えれば、iを書くのではなく、0xdeadbeef0cabba6eを何度も何度も書いてください。そのビットパターンがあなたが割り当てたスペースにすでに入っているかどうかを確認してください。

+0

Cは通常、実行時にその種のガベージコレクションを行うつもりはありません。しかし、コンパイラができることを考えるのは面白いことです。 'ptr [i]'の読み込みは一切行われないので、割り当てを省略することができます。それで、 'malloc'によって割り当てられたメモリのどれもが決して使用されないので、元に戻すことができます(「割り当てられたメモリの量」が保存されなければならない正確性のプロパティではないことがわかっている場合)。しかし、最初のものはエイリアスがつきにくいかもしれません。存在するCコンパイラが2番目のコンパイラを実行する場合は驚きます。とにかくそれが有効な変換だとは確信していません。 – Edmund

+0

私はガベージコレクションがまったく起こっていることは一度も示唆していませんでした。 C仕様は、最終結果がC抽象機械定義によって定義されたものと機能的な違いがないという唯一の条件の下で、あらゆる最適化を可能にする。 (Javaの意味でのVMについては言及していませんが、C仕様では、コンパイルされたコードの動作を定義するためのメカニズムとして抽象マシンを定義している点に注意してください)。オプティマイザは、上記のコードからの割り当てを完全に排除します。 – Sniggerfardimungus

+0

"ガベージコレクション"は、参照されていないメモリが解放される可能性がある場合について、実行時に決定するプロセスです。ここでは実行時の決定については言及していませんが、割り当てられて書き込まれたデータが使用されることはないというコンパイル時の影響があります。 – Sniggerfardimungus

2

rssと%memは、両方とも "現時点でプロセスで使用されている物理メモリ"の観点からのものです。ページングの機会がたくさんあります。 vszを追加してみてください。私はあなたが期待どおりに成長すると確信しています。

+0

あなたにぶつかる。コンパイラがデッドストアとして割り当てループを捨てることができるということについて、私が下で述べたことを仮定した場合、このメモリは予約されますがコミットされることはなく、アドレス空間がなくなるまでループする可能性があります。バイトを実際にコミットすることはありません。 :) – Joe

関連する問題