web-dev-qa-db-ja.com

すべての変数が使用されている場合、スタック、malloc、または(最近)フリーではありません

この関数を呼び出すと:

int within(struct key *node, int *value) {                      
  int length = len(node);                                       
  if ((value <= node[length-1].data) && (value >= node[0].data)) // Problematic line
    return 0;                                                   
  else if (value > node[length-1].data)                         
    return 1;                                                   
  else if (value < node[0].data)                                
    return -1;                                                  
}                                                               

Valgrindは次のエラーメッセージを表示します:

アドレス0x51f60a0はスタック、malloc、または(最近)フリーではありません

value変数とnode変数の値は正しいです。すべての変数が使用されます。そこでのメモリ管理の何が問題になっていますか?スニペットで状況がクリアされない場合は、教えてください。

8
I159

メッセージAddress 0x51f60a0 is not stack'd, malloc'd or (recently) freeは通常、より大きなValgrindエラーメッセージの一部にすぎません。

これらのValgrindエラーメッセージは通常、次のようになります。

Invalid read of size 4
   at 0x40F6BBCC: (within /usr/lib/libpng.so.2.1.0.9)
   by 0x40F6B804: (within /usr/lib/libpng.so.2.1.0.9)
   by 0x40B07FF4: read_png_image__FP8QImageIO (kernel/qpngio.cpp:326)
   by 0x40AC751B: QImageIO::read() (kernel/qimage.cpp:3621)
   Address 0xBFFFF0E0 is not stack'd, malloc'd or free'd

または

Invalid read of size 8
   at 0x40060E: free_adj_list (main.c:9)
   by 0x400844: main (main.c:65)
 Address 0x4c1d170 is 16 bytes inside a block of size 24 free'd
   at 0x4A04D72: free (vg_replace_malloc.c:325)
   by 0x400609: free_adj_list (main.c:8)
   by 0x400844: main (main.c:65)

これらのエラーメッセージの読み方

メッセージの最初の部分は、何がうまくいかなかったかを示し(「サイズ4の無効な読み取り」は、アクセスしてはならないメモリアドレスから読み取ろうとしたことを意味します)、その後にエラーが発生したバックトレースが続きます。

バックトレースの後には、アクセスしようとしたメモリアドレスに関する詳細が続きます。 Valgrindは、住所が次のとおりであるかどうかを調べることにより、ここであなたが何を意味していたかを推測します。

  • アクセスできるメモリの一部のすぐ外側(プログラムは バッファオーバーラン を実行しました)。メッセージの例はAddress 0x1002772ac is 4 bytes after a block of size 12 alloc'dになります
  • 以前に解放されたメモリのブロック内(つまり、プログラム 解放された後にメモリを使用 );例:Address 0x4c1d170 is 16 bytes inside a block of size 24 free'd

そして、これらのメッセージの後に、言及されたメモリを割り当てまたは解放した場所を示す2番目のバックトレースが続きます。

しかし、メッセージAddress 0x51f60a0 is not stack'd, malloc'd or (recently) free'dは、Valgrindがあなたが何をしようとしているのか推測できなかったことを意味します。 0x51f60a0でメモリにアクセスしようとしましたが、そのアドレスは最近解放されておらず、割り当てたメモリの他の部分の近くにありません。したがって、この場合のエラーは、バッファオーバーランでも、解放後使用エラーでもないことを合理的に確信できます。

このようなエラーをデバッグする方法

したがって、0x51f60a0は多かれ少なかれ「ランダムな」メモリアドレスであると想定できます。これには主に2つの考えられる原因が考えられます。

  • 逆参照したポインタに初期化されていない値が含まれていました。この場合、ValgrindからUse of uninitialised valueエラーメッセージも表示されます。
  • ポインタとして意図されていない値を逆参照しました-例:値は実際にはプログラム内の無関係な計算の結果である可能性があり、どういうわけか、後で使用したポインターにその値を書き込んだ

これらとは別に、もちろん、エラーが実際にはバッファオーバーランまたは解放後使用である可能性がありますが、Valgrindはそれを検出できませんでした。

プログラムでこのエラーをデバッグする方法

問題を絞り込む1つの方法は、Valgrindでアプリケーションを起動することだと思います GDBを使用 どのメモリアクセスがエラーの原因であるかを正確に調べます(nodeは悪いですか?node[length-1]は悪いですか? node[0]は悪いですか?)次に、そもそも悪い値がどのようにしてそこに来たのかを調べます。

29
oliver

あなたの比較は
*value <= node[length-1].data
ない
value <= node[length-1].data

IOW、value変数の前にアスタリスクがありません。

2
KevinDTimm

"スタックされていない、mallocされていない、または(最近)解放されていない"の問題の原因。これが私のような検索エンジンによってここに指示された誰かに役立つことを願っています。

私の場合、サイズ585のヒープ配列pを割り当てました。しかし、次に、733〜1300のインデックス範囲でpにアクセスしようとしました。そしてvalgrindはちょうどそのメッセージを示しました。

1
duleshi