2010-12-16 23 views
3

gcc 4.5.1 c89ストールアップ後にメモリを解放できません

メモリを解放しようとしています。しかし、私がvalgrindでチェックすると、メモリは解放されていません。私は何が間違っているのだろうと思っています。

typedef struct tag_cand_results { 
    char *candidate_winners[NUMBER_OF_CANDIDATES]; 
} cand_results; 

が、私はこのような構造のオブジェクトを作成します:

cand_results *results = NULL; 

私は構造のためのいくつかのメモリを割り当てる

は、私は次のような構造を持っています。

results = calloc(1, sizeof *results); 

それ

results->candidate_winners[0] = strdup("Steve Martin"); 
results->candidate_winners[1] = strdup("Jack Jones"); 

にいくつかのデータを割り当てそれから私は、割り当てられたすべてのメモリを解放しよう:

free(results->candidate_winners[0]); 
free(results->candidate_winners[1]); 
free(results); 

Just to be safe assign to NULL 
results = NULL; 

私はvalgrindのからの次の出力を取得します。

==8119== 72 bytes in 6 blocks are definitely lost in loss record 1 of 2 
==8119== at 0x4A05E46: malloc (vg_replace_malloc.c:195) 
==8119== by 0x3FE2E82A91: strdup (strdup.c:43) 
==8119== by 0x400E5A: main (driver.c:116) 
==8119== 
==8119== 72 bytes in 6 blocks are definitely lost in loss record 2 of 2 
==8119== at 0x4A05E46: malloc (vg_replace_malloc.c:195) 
==8119== by 0x3FE2E82A91: strdup (strdup.c:43) 
==8119== by 0x400E72: main (driver.c:117) 

なぜメモリが解放されていないのですか?

任意の提案のための多くのおかげで、

+0

あなたはValgrindのは、まだこのように文句どの最小*完全*プログラムを投稿することができます。 – NPE

+0

私のソースコードのどこかで何かが起こっています。下記のPaxにコメントを投稿しました。 – ant2009

答えて

4

そのイベントの実際シーケンスである場合には、valgrindの間違っています。メモリは解放されたです。あなたのコメントで要求された最良の技術に関しては


、通常、私はいくつかのものをチェックするために

:-)この場合にはvalgrindのを言うが、おそらくないだろう。

  • strdup(some_string)(どちらの場合も)の代わりにmalloc(30)を呼び出すとどうなりますか?
  • (malloc-or-strdup)/free pairsを一度に1つずつ削除して、何が起こるかを確認します。
  • 私はあなたの実際のコードを見たことがないので、すべてstrdupfree行の前後にprintfを置いて、それらがすべて実行されていることを確認してください。
  • 小さなプログラムをここに投稿してください(問題を示しています)ので、確認してください。何が価値があるために

、以下の小さな(完全な)プログラム:以下のvalgrindの出力で

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

#define NUMBER_OF_CANDIDATES 10 
typedef struct tag_cand_results { 
    char *candidate_winners[NUMBER_OF_CANDIDATES]; 
} cand_results; 

int main (void) { 
    cand_results *results = NULL; 

    results = calloc(1, sizeof *results); 

    results->candidate_winners[0] = strdup("Steve Martin"); 
    results->candidate_winners[1] = strdup("Jack Jones"); 

    free(results->candidate_winners[0]); 
    free(results->candidate_winners[1]); 
    free(results); 

    results = NULL; 

    return 0; 
} 

結果:つまり

==9649== Memcheck, a memory error detector 
==9649== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al. 
==9649== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for 
     copyright info 
==9649== Command: ./qq 
==9649== 
==9649== 
==9649== HEAP SUMMARY: 
==9649==  in use at exit: 0 bytes in 0 blocks 
==9649== total heap usage: 3 allocs, 3 frees, 64 bytes allocated 
==9649== 
==9649== All heap blocks were freed -- no leaks are possible 
==9649== 
==9649== For counts of detected and suppressed errors, rerun with: -v 
==9649== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 13 from 8) 

、問題なし。だからあなたの場合には別のものかもしれません(環境問題かもしれません)。この特定の実行は、Ubuntu Lucid(10.04)、gcc 4.4.3、c89モードで実行されました。

私はシステム上でそのコード正確にを入力することをお勧めします。私はコンパイルしてテストするために使用するコマンドラインは:

gcc -std=c89 -o qq qq.c 
valgrind ./qq 
+0

私のプロジェクトを別のブランチに切り替えるだけです。無関係なコードと実際にメモリを割り当てているソースコードだけをすべて取り出しました。コードは私が投稿したもののように見えます。記憶は解放された。だから、どこか別のことが起こっていると思う。私はさらに調査する必要があります。しかし、どのようなメモリエラーを見つけるための最良の技術は何ですか? – ant2009

+0

ありがとうございました。私は自分のソースコードをチェックし、新しい情報で報告します。ありがとう。 – ant2009

1

「6つのブロックで72のバイト」、「スティーブ・マーティン」または「ジャック・ジョーンズ」のような音はありません。あなたはある時点でポインタを上書きしていません(!)?

2

割り当て/解放に明らかなエラーはありません。

結果の内容が何らかの形で変更されたようです(ワイルドポインタによって上書きされますか?)。

strdupを使用して割り振り直後と解放する直前に、printf( "%p"、...)を使用してポインタのメモリアドレス値を出力することが簡単にチェックできます。それが変更された場合:ビンゴ!

また、resultへのポインタが変更された(そして以降では値が指し示される)可能性があります。

ここでポインタが実際にどこで発生するのかを特定する方法が変更されている場合は、

1つの解決方法は、デバッガを使用してプログラムを実行することです。これは非常に時間がかかることもありますが、通常は機能します。しかし、これがオプションでない場合、別の方法があります。私は通常、デバッガを使用するよりも速く見つけます。

割り当てられたポインタのコピーを別の変数に保存してください。破損したポインタがあるメモリチャンクから遠ざけることができます(通常はグローバルで行います)。制御フローで今すぐ

は次のようにアサーションを置く:

のassert(結果== saved_result)。

アサーションが失敗し、最終的に問題が見つかるはずです。

最後に、最終プロジェクトに残すべきではないアサーションを削除することを忘れないでください。そのことを確認するには、saved_result変数を削除してください。アサーションが残っていると、プログラムはデバッグモードでコンパイルされません。

2

gdbでアプリケーションをデバッグし、 "watch"コマンドでポインタが変更されたかどうかを監視することもできます。主な機能にブレークポイントを設定し、問題がどこにあるのかを確認するためにフォローアップを行います。

よろしく、

ミゲル

関連する問題