Readdir / closedir - Valgrind показывает «недопустимое чтение» - PullRequest
3 голосов
/ 06 августа 2011

Размещение фрагментов моего кода здесь.Я пытаюсь разобраться с отладкой.

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)

Любая помощь будет высоко оценена.Спасибо

Ответы [ 3 ]

4 голосов
/ 06 августа 2011

Вы не должны получать доступ к данным, возвращаемым readdir() после вызова closedir(). Это связано с тем, что closedir() может освободить любые ресурсы (например, память), выделенные в opendir / readdir.

Если вы хотите сохранить структуру dirent *, вы можете переключиться на readdir_r вариант readdir (с другим набором параметров).

ОБНОВЛЕНИЕ: Расшифровка вывода 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() (вызванный пропущенным обратным следом). Почему данные неверны? Есть субмессия

        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)

Байт недействителен (не разрешен для чтения), поскольку он является частью сегмента памяти, который был свободен-d (вы не можете читать из памяти, которую вы только что освободили-d). Кто это сделал? Посмотрите на обратный след: closedir был вызывающим свободным.

0 голосов
/ 06 августа 2011

К тому времени, как вы дойдете до strcat(), вы уже вышли из цикла while. Цикл while завершается один раз s_dirent - NULL.

Но как только s_direct становится пустым, вы запускаете это:

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

... который пытается разыменовать s_dirent. Таким образом, valgrind сообщает вам проверить вызов strcat (), вызываемый из backup_manager.c: 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 голосов
/ 06 августа 2011

s_dirent == NULL, проверьте условие выхода из петли while.

...