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)
任何帮助将不胜感激。 谢谢
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您不应访问调用
closedir()
后由readdir()
返回的数据。这是因为 Closedir() 可能会释放在 opendir/readdir 中分配的任何资源(例如内存)。如果你想保存 dirent* 结构,你可以切换到 readdir 的
readdir_r
变体(具有不同的参数集)。更新:Valgrind 输出的解码:
Valgrind 表示错误是
读取无效数据,大小为 1 字节
,这不是内存泄漏。这是不正确的内存访问。这次读取的参与者是 strcat()(由跳过的回溯调用)。为什么数据无效?有 submessage该字节无效(不允许读取),因为它是 free-d 内存段的一部分(您无法从刚刚 free-d 的内存中读取)。这是谁干的?查看回溯:
closedir
是 free 的调用者。You should not access data, returned by
readdir()
after calling aclosedir()
. This is becauseclosedir()
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:
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 thestrcat()
(called by skipped backtrace). Why the data is invalid? There is submessageThe 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.s_dirent == NULL
,检查while
循环退出条件。s_dirent == NULL
, check thewhile
loop exit condition.当您到达
strcat()
时,您已经退出 while 循环。一旦s_dirent
为 NULL,while 循环就会退出。但是,一旦 s_direct 为 NULL,您就运行以下命令:
...它会尝试取消引用 s_dirent。因此,valgrind 然后告诉您检查从 backup_manager.c:254 调用的 strcat() 调用:
我猜您只有在处理包含“.”、“条目的空目录时才会遇到此问题” ..”,或者只包含以“.”开头的隐藏文件的目录?
By the time you get to the
strcat()
, you've already exited the while loop. The while loop exits onces_dirent
is NULL.But as soon as
s_direct
is NULL, you run this:...which attempts to dereference s_dirent. Thus, valgrind then tells you to check the call to strcat() being called from 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 "."?