6

私はスクラッチボックスのクロスコンパイル環境にいて、これを持っています

#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;
        }
    }
}

バイナリを実行して実行すると

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

プロセスのメモリフットプリントの増加は見られません。何故ですか?

4

3 に答える 3

5

あなたはおそらく非常に最適化されたものを構築しました。

最近のほとんどのシステムでは、gccはmallocがエイリアスされていないポインタを返すことを知っています。つまり、同じポインタを2回返すことはなく、「ライブ」で保存したポインタを別の場所に返すこともありません。

これを想像するのは非常に難しいと思いますが、mallocが一度呼び出され、その戻り値が何度も使用されている可能性があります。理由は次のとおりです。

それはあなたの記憶が死んだ店であることを知っています。すなわち:あなたはそれに書き込みますが、それは決して読み取られません。ポインタはエイリアス化されていないことがわかっているため、他の場所から読み取るためにエスケープされておらず、揮発性としてマークされていません。あなたのforループ自体は/could/捨てられます。

その時点で、同じメモリを何度も使用する可能性があります。

これが私が信じがたい理由です:gccはmallocについてどれだけ知っていますか?Mallocは、「から」と呼ばれるグローバルな「回数を増やす」など、あらゆる種類の副作用を引き起こす可能性があります。通話を切断し、副作用がないと想定するのは本当に奇妙に思えます。地獄、'malloc'は、100回目の呼び出しごとにNULLを返すように実装できます(仕様どおりではないかもしれませんが、誰が言っているのでしょうか)。

それがしていないのは、あなたに代わってそれを解放することです。それは、「知ることができた」ことを超えて、「許可されていないことを行う」という領域にまで及びます。あなたはメモリをリークすることを許されています、それはそうかもしれませんが、ラメです。

ここでは2つのことが役立ちます:1)environmenetをコンパイルします:どのos、コンパイラ、およびコマンドラインフラグ。

2)最終的なバイナリの逆アセンブル。(objdumpまたはコンパイラから)

于 2012-05-25T00:15:19.333 に答える
2

rssと%memはどちらも、「現在プロセスで使用されている物理メモリ」の観点からのものです。それはものをページアウトする機会がたくさんあります。vszを追加してみてください。私はあなたが期待するようにそれが成長するに違いない。

于 2012-05-25T00:14:03.820 に答える
-2

コンパイラは、使用していないことに気付いたときに、割り当てられたメモリを解放することで(コードの最適化されたバージョンがmallocを実行できると仮定して)支援します。ポインタの値を出力してみてください(printf( "0x%x"、ptr);)-繰り返し値が返されるのではないかと思います。より信頼性の高いチェックでは、割り当てられたメモリにすでにその文字列が含まれているかどうかを確認して、既知のビット文字列をメモリに書き込みます。つまり、iを書き込む代わりに、割り当てたスペースにそのビットパターンがすでに存在するかどうかを確認した後、0xdeadbeef0cabba6eを何度も書き込みます。

于 2012-05-25T00:06:07.217 に答える