2011-08-06 21 views
3

ここに自分のコードのスニペットを掲載します。私はデバッグの拠点を得ようとしています。Readdir/closedir - Valgrindは「無効な読み取り」を示します

struct dirent *s_dirent; 
char path[300]; 
.... 
bzero(path,300); 
... 
fd_dir = opendir(path); 
while((s_dirent = readdir(fd_dir))!=NULL) 
{ 
    if(s_dirent->d_name[0] == '.') 
      continue; 
    else 
      break; 
} 
if(s_dirent == NULL) 
{ 
    if(closedir(fd_dir)!=0) 
     perror("Error on closedir"); 
} 
else 
{ 

    if(closedir(fd_dir)!=0)/*Line number 249*/ 
     perror("Error on closedir"); 

    /*some comments*/ 
    strcat(path,"/"); 
    strcat(path,s_dirent->d_name);/*Line number 254*/ 
} 

Valgrindの出力:

==3287== Invalid read of size 1 
==3287== at 0x40069E0: strcat (mc_replace_strmem.c:176) 
==3287== by 0x804D6B4: online_bck (backup_manager.c:254) 
==3287== by 0x8049F96: on_bck_beg (TxFS_manager.c:181) 
==3287== by 0x8049818: handler (Reader.c:236) 
==3287== by 0xBF5F18: start_thread (in /lib/libpthread-2.12.90.so) 
==3287== by 0xB37A2D: clone (in /lib/libc-2.12.90.so) 
==3287== Address 0x402a39b is 35 bytes inside a block of size 32,792 free'd 
==3287== at 0x40057F6: free (vg_replace_malloc.c:325) 
==3287== by 0xAF6C67: closedir (in /lib/libc-2.12.90.so) 
==3287== by 0x804D65A: online_bck (backup_manager.c:249) 
==3287== by 0x8049F96: on_bck_beg (TxFS_manager.c:181) 
==3287== by 0x8049818: handler (Reader.c:236) 
==3287== by 0xBF5F18: start_thread (in /lib/libpthread-2.12.90.so) 
==3287== by 0xB37A2D: clone (in /lib/libc-2.12.90.so) 

すべてのヘルプは高く評価されます。 ありがとう

+0

コードの大部分を投稿して申し訳ありません。 –

答えて

4

closedir()を呼び出した後、readdir()によって返されたデータにはアクセスしないでください。これは、closedir()がopendir/readdirに割り当てられたリソース(たとえばメモリ)を解放する可能性があるためです。

dirent * structを保存する場合は、readdirの変形(パラメータの異なるセット)をreaddir_rに切り替えることができます。

UPDATE:Valgrindの出力のデコード:

 V - note single space here; it is beginning of error message. 
==3287== Invalid read of size 1 
==3287== at 0x40069E0: strcat (mc_replace_strmem.c:176) 

backtrace skipped 

Valgrindのは、メモリリークされていない、エラーがReading of invalid data, sized 1 byteであることを述べています。間違ったメモリアクセスです。そしてこの読者の俳優はstrcat()です(スキップされたバックトレースによって呼び出されます)。データが無効な理由それは(あなたは、単に自由-Dメモリから読み取ることができない)自由-Dだったメモリ・セグメントの一部であるため、サブメッセージ

 VV - note two spaces here, it is continuation of error message 
==3287== Address 0x402a39b is 35 bytes inside a block of size 32,792 free'd 
==3287== at 0x40057F6: free (vg_replace_malloc.c:325) 
==3287== by 0xAF6C67: closedir (in /lib/libc-2.12.90.so) 

があるバイトが(から読み取ることが許可されていない)は無効です。誰だ?バックトレースを見てください:closedirは無料の発信者でした。

+1

またはおそらくそれ以外の場所にコピーしてくださいclosedir()を呼び出す前に –

+0

はい、しかしreaddir_rはdirentをユーザ提供のバッファにコピーなしで直接置きます。私の答えは純粋な推測であり、Linux、SUS、Solarisのマニュアルページreaddir/closedirのどちらもあなたのケースを説明していないと言ってください。しかし、Valgrindの出力によれば、strcmpはfree-dデータにアクセスしようとし、解放できるのはclosedirだけです。 – osgx

+0

あなたの言うことは考えられますが、readdir()またはclosedir()のマニュアルページでは、readdir()によって返された静的バッファポインタがclosedir()によって割り当て解除されたことには言及していません。解放されたコールスタックを見ると、それは起こったように見えます: '0x40057F6:free(vg_replace_malloc.c:325)' by 0xAF6C67:closedir(/lib/libc-2.12.90にあります。 so) ' –

0

s_dirent == NULLループの終了条件はwhileです。

+0

@ Steave-o前にやったNULLのチェックを投稿して申し訳ありません。しかし、私はすでにその状態をチェックしていました。あなたの興味をお寄せいただきありがとうございます –

0

strcat()になるまでには、すでにwhileループを終了しています。 whileループは、s_direntがNULLになると終了します。間接参照s_direntにしようと

strcat(path,"/"); 
strcat(path,s_dirent->d_name);/*Line number 254*/ 

...:できるだけ早くs_directがNULLであるよう

しかし、あなたがこれを実行します。したがって、valgrindの後、()backup_manager.cから呼び出されSTRCATへの呼び出しをチェックすることを示しています:254:

==3287== Invalid read of size 1 
==3287== at 0x40069E0: strcat (mc_replace_strmem.c:176) 
==3287== by 0x804D6B4: online_bck (backup_manager.c:254) 

私はあなたが含まれている空のディレクトリを処理している場合にのみ、あなたがこれを打っている推測しています"。"、 ".."、または "。"で始まる隠しファイルのみを含むディレクトリのエントリ?

+0

私は前に行ったNULLのチェックを投稿して申し訳ありません。しかし、私はすでにその状態をチェックしており、エラーにつながることはありません。あなたの興味をお寄せいただきありがとうございます –

関連する問題