2011-09-14 26 views
0
Environment: uname -a: 2.6.38 #18 Thu Apr 28 12:38:48 CEST 2011 armv5tejl GNU/Linux 
    GCC: 
    gcc -v 
    Using built-in specs. 
    Target: arm-linux-gnueabi 
    Configured with: ../src/configure -v --with-pkgversion='Debian 4.4.5-8' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.4 --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --disable-sjlj-exceptions --enable-checking=release --build=arm-linux-gnueabi --host=arm-linux-gnueabi --target=arm-linux-gnueabi 
    Thread model: posix 
    gcc version 4.4.5 (Debian 4.4.5-8) 

以下のコードでは、すべて正しく動作しているようですが、割り当てられたメモリは解放されていないようです。私の構造体メソッドはリンクされたリストではありません。ダイナミック構造を解放するとメモリが解放されない

ガベージコレクタが喜んでいつでも行動を取ることを理解して、「明らかに」と言います。それでも、テストコードが実行されたときにRSSが徐々に増加するのを見て、各テストで同じ容量のスペースを割り当てているので、割り当てが再利用されると思います。

私のコードは、単純な動的構造を実装:

struct _aemErrors 
{ 
    int stored; // true = stored to sql 
    int mailed; // true = mailed to alert 
    int nType; // LOG_DEBUG LOG_INFO... 
    int time; // error triggered timestamp 
    int line; // line in file that triggered 
    char *cFunction; // function that triggered 
    char *cDesc; // description of problem 
}; 
struct _aemErrors **aemErrors; 
int aemErrorsCount; 

構造は、使用される場合、のmalloc()またはのstrdup()

構造の各レコードのいずれかを使用して作成された2つの文字のポインタを有していますこれで初期化されますので、

int AddaemError(void) 
{ 
    ++aemErrorsCount; 
    aemErrors = (struct _aemErrors **)realloc(aemErrors, (aemErrorsCount+1) *  sizeof(struct _aemErrors *)); 
    aemErrors[aemErrorsCount] = (struct _aemErrors *)malloc(sizeof(struct _aemErrors)); 
    return(aemErrorsCount); 
} 

int main(int argc,char **argv) 
{ 

    // initialize the structure 
    aemErrors=NULL; 
    aemErrorsCount=-1; 

    int nPtr=0; 
    int nLoopCount=0; 
    while (nLoopCount<100) 
    { 

    for (nPtr=0;nPtr<1000;nPtr++) 
     { 
     nPtr=AddaemError(); 
     aemErrors[nPtr]->stored=false; 
     aemErrors[nPtr]->mailed=false; 
     aemErrors[nPtr]->nType=LOG_ALERT; 
     aemErrors[nPtr]->nTime=time(NULL); 
     aemErrors[nPtr]->line=0; 
     aemErrors[nPtr]->cFunction=strdup("ThisIsATest"); 
     aemErrors[nPtr]->cDesc=strdup("ThisIsATest"); 
    } 
    FreeaemErrors(); 
    sleep(5); 
    ++nLoopCount; 
    } 
    return(0); 
} 

ループがスピンするにつれて、私はRSSがそれに応じて上昇するのを見ます。私は内部メモリ状態テスター(図示せず:procファイルシステムのデータを読み込む)とランタイムをカプセル化する外部シェルプロセスを使用して、毎秒メモリパフォーマンスデータを与えています。注:この問題は監視なしで発生するため、結果に影響していないことがわかります。

は今、私はすべてを解放したい:

// cleanup the dynamic structure 
int FreeaemErrors(void) 
{ 
    if (aemErrors==NULL) 
     return(true); 
    int i=0; 

    printf("FreeaemErrors():Count=%i\n",aemErrorsCount); 

    for(i = 0; i <= aemErrorsCount; i++) 
    { 
     free(aemErrors[i]->cFunction); 
     free(aemErrors[i]->cDesc); 
     free(aemErrors[i]); 
     aemErrors[i]->cFunction=NULL; 
     aemErrors[i]->cDesc=NULL; 
     aemErrors[i]=NULL; 
    } 
    printf("Done. Free root\n"); 
    free(aemErrors); 
    aemErrors=NULL; 
    aemErrorsCount=-1; 
    printf("Returning\n"); 
    return(true); 
} 

は、だから私はFreeaemErrorsを発行します();次にメモリを見て、数秒待ってください。それは減少しません。

次回にpopulateループを実行し、1000レコードをおそらくクリーンな構造体に追加すると、RSSが再び立ち上がります。

私は現時点では少し狂っています。

アイデア、誰ですか?


あなたのご意見をお寄せいただきありがとうございます。

さまざまな構造サイズでかなりのテストをした後、私たちは一定のサイズに達したら、すべてを解放すると、RSSは私が期待していたところに戻ってきます。しかし、それほどではない。

私の例のように、新しい割り当てのための連続したメモリが利用できないため、realloc()が発生したときに、メモリの断片化とプログラムがどのように肥大化するかを学びました。

この問題に対応するには、(a)n要素のブロックを保持するように構造体サイズを初期化する必要があります(nは必要に応じて40から100までです)。 (b)構造体が成長する必要があるとき(私たちは最初の割り当てを使い果たした)、元の構造体の複製を作成し、元の構造体を完全に解放した後、サイズn + increment_sizeの新しい領域を割り当ててから、古い、無料で古い。新しいレコード要求が割り当てカウント内にある場合、すべての関数は現在の割り当て番号を返します。

新しいスキームはrealloc()をまったく使用しません。問題を考えると、私はこれをプラスと考えています。

複雑な場合もありますが、場合によっては遅くなるかもしれませんが、少なくともメモリはチェックされているようです。

+3

「浄化する」ツールについて聞いたことがありますか?私はすべてのコードを見る傾向がありません。おそらくあなたはそれを少し狭めることができます。 –

+1

あなたはAddaemError()でaemErrorCountをインクリメントしてからもう1つスペースを割り当てます。つまり、配列内で要素[0]を使用することはありませんが、自由にします。また、nPtrを呼び出してループ内でインクリメントしています。この回答はありません:) – tinman

+1

@tinmanが正しいです。また、「ガベージコレクタ」について、ガベージコレクタとは何かについて話します。そして、「記憶を見ている」ことはどういう意味ですか、それは減少していませんか?あなたは 'トップ'の出力を見ていますか? – user786653

答えて

1

freeまたはreallocでメモリを解放しても、システムに返されることはまったく意味しません。ヒープ機構は、これらのページをどこかに置いて、次の割り当てに利用できるようにします。あなたが本当にあなたのすべてのメモリを解放するかどうか本当に知りたい場合は、valgrindのようなツールを使用してください。これは、あなたのプロセスが割り当てたすべてのメモリを解放した場合は "postmortem"となります。そうでない場合は、後で解放せずに割り当てるコードの場所を指し示します。

関連する問題