Readdir/closedir-Valgrind显示;无效的read";
在这里发布我的代码片段。我正试图在调试方面站稳脚跟Readdir/closedir-Valgrind显示;无效的read";,c,linux,valgrind,readdir,C,Linux,Valgrind,Readdir,在这里发布我的代码片段。我正试图在调试方面站稳脚跟 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; }
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)
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
我们将非常感谢您的帮助。
感谢
s\u dirent==NULL
,检查while
循环退出条件。当您到达strcat()
时,您已经退出while循环。当s\u dirent
为空时,while循环退出一次
但只要s_direct
为空,您就可以运行以下命令:
strcat(path,"/");
strcat(path,s_dirent->d_name);/*Line number 254*/
…试图取消对s_dirent的引用。因此,valgrind然后告诉您检查从backup_manager调用strcat()的调用。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)
我猜只有在处理包含“.”“…”项的空目录或仅包含以“.”开头的隐藏文件的目录时,您才会遇到此问题。您不应该访问调用
closedir()
后由readdir()
返回的数据。这是因为closedir()
如果要保存dirent*struct,可以切换到readdir的变体(使用不同的参数集)
更新: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)
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()
(被跳过的回溯调用)。为什么数据无效?有子消息
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的内存中读取)。这是谁干的?查看backtrace:
closedir
是免费的调用者。我很抱歉没有发布大部分代码。我做到了now@Steave-o很抱歉,我没有像以前那样邮寄空支票。但我已经检查过这种情况。谢谢你的关注,很抱歉没有像我以前那样把空支票寄出去。但我已经检查过这种情况,这并不是导致错误的原因。感谢您的关注者,在调用closedir()Yes之前,可以将其复制到其他地方,但是readdir\r将直接将dirent放置到用户提供的缓冲区中,而不复制。我应该说,我的答案纯粹是猜测,readdir/closedir的Linux、SUS和Solaris手册页都没有描述您的情况。但是Valgrind output说,strcmp试图访问free-d数据,而closedir是唯一可以释放它的人。虽然您的说法听起来似乎有道理,但readdir()或closedir()手册页都没有提到由readdir()返回的静态缓冲区指针是由closedir()释放的。查看被释放的调用堆栈,看起来确实是这样的:在0x40057F6:free(vg_replace_malloc.c:325)
由0xAF6C67:closedir(in/lib/libc-2.12.90.so)调用,或者将closedir移动到strcat()之后?@Stéphane:我找不到任何POSIX文档可以释放由readdir
返回的缓冲区,但这似乎是POSIX中的一个缺陷。显然,他们的意图是将缓冲区置于DIR
结构中,因为对于一个打开的DIR
调用readdir
不允许对另一个DIR
调用readdir
返回的dirent
。除非closedir
释放缓冲区,否则无法在不泄漏内存的情况下满足这些要求。