Readdir/closedir - Valgrind 显示“无效读取”

发布于 2024-11-28 14:05:46 字数 1501 浏览 1 评论 0原文

在这里发布我的代码片段。我正在尝试为调试奠定基础。

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)

任何帮助将不胜感激。 谢谢

Posting snippets of my code here. I am trying to get a footing around debugging.

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 output:

==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)

Any help will be highly appreciated.
Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

稚气少女 2024-12-05 14:05:46

您不应访问调用 closedir() 后由 readdir() 返回的数据。这是因为 Closedir() 可能会释放在 opendir/readdir 中分配的任何资源(例如内存)。

如果你想保存 dirent* 结构,你可以切换到 readdir 的 readdir_r 变体(具有不同的参数集)。

更新: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 表示错误是读取无效数据,大小为 1 字节,这不是内存泄漏。这是不正确的内存访问。这次读取的参与者是 strcat()(由跳过的回溯调用)。为什么数据无效?有 submessage

        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)

该字节无效(不允许读取),因为它是 free-d 内存段的一部分(您无法从刚刚 free-d 的内存中读取)。这是谁干的?查看回溯:closedir 是 free 的调用者。

You should not access data, returned by readdir() after calling a closedir(). This is because closedir() may free any resources (e.g. memory), allocated in opendir/readdir.

If you want to save dirent* struct, you can switch to readdir_r variant of readdir (with different set of parameters).

UPDATE: Decoding of Valgrind output:

        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 says that error is Reading of invalid data, sized 1 byte, which is not a Memory Leak. It is incorrect memory access. And the actor of this read is the strcat() (called by skipped backtrace). Why the data is invalid? There is submessage

        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)

The byte is invalid (not allowed to be read from) because it is part of memory segment which was free-d (you can't read from the memory you just free-d). Whom did this? Look at backtrace: closedir was the caller of free.

本宫微胖 2024-12-05 14:05:46

s_dirent == NULL,检查while循环退出条件。

s_dirent == NULL, check the while loop exit condition.

寒尘 2024-12-05 14:05:46

当您到达 strcat() 时,您已经退出 while 循环。一旦 s_dirent 为 NULL,while 循环就会退出。

但是,一旦 s_direct 为 NULL,您就运行以下命令:

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

...它会尝试取消引用 s_dirent。因此,valgrind 然后告诉您检查从 backup_manager.c:254 调用的 strcat() 调用:

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

我猜您只有在处理包含“.”、“条目的空目录时才会遇到此问题” ..”,或者只包含以“.”开头的隐藏文件的目录?

By the time you get to the strcat(), you've already exited the while loop. The while loop exits once s_dirent is NULL.

But as soon as s_direct is NULL, you run this:

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

...which attempts to dereference s_dirent. Thus, valgrind then tells you to check the call to strcat() being called from 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)

I'm guessing you're hitting this only when you're processing an empty directory which contains entries for ".", "..", or directories that only contain hidden files which start with "."?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文