免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 20219 | 回复: 11
打印 上一主题 下一主题

程序运行时,出现错误double free or corruption,什么原因导致的? [复制链接]

论坛徽章:
2
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:57:09
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-06-05 12:46 |只看该作者 |倒序浏览
这是我照着一本书上的思路,自己写了个统计一个目录下文件的类型和数量的小程序,但是运行时
出现错误double free or corruption,出错的地方在
// if(closedir(dp)<0)
//     printf("can not close the directory %s",pathname);
//     这个地方是不是会产生递归调用多次的情况?

//if(dirp==NULL)
// closedir(dp);

这是关闭dp的两种写法,都会出错,只要不进行关闭,程序没有问题.
我本来感觉是由于递归产生了多次关闭,导致的错误,于是就改成了蓝字的写法,但是还是一样的错误,哪位大哥给指点下!!非常感谢!

#include <dirent.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <stdio.h>

static int nreg,ndir,nblk,nfifo,nalink,nsock,ntot;
static char *pathname;
int do_dir()
{
    struct stat statbuf;
    struct dirent *dirp;
    DIR *dp;
    int ret;
    char *ptr;

    if(lstat(pathname,&statbuf)<0)
        perror("stat error");

   // printf("after lstat %s",pathname);

    if(S_ISDIR(statbuf.st_mode)==0)
    {
        printf("this is a file %s\n",pathname);
        switch(statbuf.st_mode&S_IFMT)
        {
            case S_IFREG:
                nreg++;break;
            case S_IFBLK:
                nblk++;break;
            case S_IFIFO:
                nfifo++;break;
            case S_IFLNK:
                nalink++;break;
            case S_IFSOCK:
                nsock++;break;
            default:
                printf("unknown file type!\n");
        }

        printf("%d %d %d %d %d \n",nreg,nblk,nfifo,nalink,nsock);
        return 0;
    }

    ptr = pathname + strlen(pathname);
    *ptr++ = '/';
    *ptr = 0;
   

    ndir++;
    if((dp=opendir(pathname))==NULL)
        perror("opendir error");
    while((dirp=readdir(dp))!=NULL)
    {
        if(strcmp(dirp->d_name,".")==0||strcmp(dirp->d_name,"..")==0)
            continue;
        strcpy(ptr,dirp->d_name);
        printf("%s\n",pathname);
        ret = do_dir();
    }
    ptr[-1]=0;//what's meanning?
   // if(closedir(dp)<0)
   //     printf("can not close the directory %s",pathname);
   //     这个地方会产生递归调用多次的情况,应在只是在最后一次的时候关闭closedir
   //if(dirp==NULL)
      // closedir(dp);

    return ret;
}

int pre_handling(char *path)
{
    int ret;
    int length = strlen(path);
    pathname = malloc(length+1);
    strcpy(pathname,path);
    pathname[length]=0;
    printf("current path handling = %s\n",path);

    ret = do_dir();
    return ret;
}

void display()
{
    if((ntot=nreg+ndir+nblk+nfifo+nalink+nsock)==0)
        ntot=1;
    printf("regular file    = %7d,%5.2f\n",nreg,100.0*nreg/ntot);
    printf("dictionary file = %7d,%5.2f\n",ndir,100.0*ndir/ntot);
    printf("block file      = %7d,%5.2f\n",nblk,100.0*nblk/ntot);
    printf("fifo file       = %7d,%5.2f\n",nfifo,100.0*nfifo/ntot);
    printf("link file       = %7d,%5.2f\n",nalink,100.0*nalink/ntot);
    printf("nsock file      = %7d,%5.2f\n",nsock,100.0*nsock/ntot);
}

int main(int argc,char *argv[])
{
    int ret;
    if(argc!=2)
        perror("patameters not match\n");
   
    ret = pre_handling(argv[1]);
    display();
    return 0;

}

论坛徽章:
2
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:57:09
2 [报告]
发表于 2009-06-05 17:08 |只看该作者
怎么没有人回答我!:em11:

论坛徽章:
0
3 [报告]
发表于 2009-06-05 17:29 |只看该作者
运行了你的程序,没有错误

[dsm@FC4vxW ~]$ ./test Documents/
current path handling = Documents/
after lstat Documents/regular file    =       0, 0.00
dictionary file =       1,100.00
block file      =       0, 0.00
fifo file       =       0, 0.00
link file       =       0, 0.00
nsock file      =       0, 0.00

论坛徽章:
2
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:57:09
4 [报告]
发表于 2009-06-05 17:41 |只看该作者

回复 #3 liying_gg 的帖子

我把错误的注释了,当然没错了!呵呵!
我的意思是加上注释时,老是会报错,不知道为什么?

[ 本帖最后由 liujunwei1234 于 2009-6-5 21:45 编辑 ]

论坛徽章:
84
每日论坛发贴之星
日期:2015-12-29 06:20:00每日论坛发贴之星
日期:2016-01-16 06:20:00每周论坛发贴之星
日期:2016-01-17 22:22:00程序设计版块每日发帖之星
日期:2016-01-20 06:20:00每日论坛发贴之星
日期:2016-01-20 06:20:00程序设计版块每日发帖之星
日期:2016-01-21 06:20:00每日论坛发贴之星
日期:2016-01-21 06:20:00程序设计版块每日发帖之星
日期:2016-01-23 06:20:00程序设计版块每日发帖之星
日期:2016-01-31 06:20:00数据库技术版块每日发帖之星
日期:2016-01-16 06:20:00程序设计版块每日发帖之星
日期:2016-01-16 06:20:00程序设计版块每日发帖之星
日期:2016-01-14 06:20:00
5 [报告]
发表于 2009-06-05 22:10 |只看该作者
man 3 free

...
NotesThe Unix98 standard requires malloc(), calloc(), and realloc() to set errno to ENOMEM upon failure. Glibc assumes that this is done (and the glibc versions of these routines do this); if you use a private malloc implementation that does not set errno, then certain library routines may fail without having a reason in errno.
Crashes in malloc(), free() or realloc() are almost always related to heap corruption, such as overflowing an allocated chunk or freeing the same pointer twice. Recent versions of Linux libc (later than 5.4.23) and GNU libc (2.x) include a malloc implementation which is tunable via environment variables. When MALLOC_CHECK_ is set, a special (less efficient) implementation is used which is designed to be tolerant against simple errors, such as double calls of free() with the same argument, or overruns of a single byte (off-by-one bugs). Not all such errors can be protected against, however, and memory leaks can result. If MALLOC_CHECK_ is set to 0, any detected heap corruption is silently ignored and an error message is not generated; if set to 1, the error message is printed on stderr, but the program is not aborted; if set to 2, abort() is called immediately, but the error message is not generated; if set to 3, the error message is printed on stderr and program is aborted. This can be useful because otherwise a crash may happen much later, and the true cause for the problem is then very hard to track down.
...

论坛徽章:
84
每日论坛发贴之星
日期:2015-12-29 06:20:00每日论坛发贴之星
日期:2016-01-16 06:20:00每周论坛发贴之星
日期:2016-01-17 22:22:00程序设计版块每日发帖之星
日期:2016-01-20 06:20:00每日论坛发贴之星
日期:2016-01-20 06:20:00程序设计版块每日发帖之星
日期:2016-01-21 06:20:00每日论坛发贴之星
日期:2016-01-21 06:20:00程序设计版块每日发帖之星
日期:2016-01-23 06:20:00程序设计版块每日发帖之星
日期:2016-01-31 06:20:00数据库技术版块每日发帖之星
日期:2016-01-16 06:20:00程序设计版块每日发帖之星
日期:2016-01-16 06:20:00程序设计版块每日发帖之星
日期:2016-01-14 06:20:00
6 [报告]
发表于 2009-06-05 22:13 |只看该作者
注意错误处理,opendir()失败时只打印错误信息,没有退出。
    if((dp=opendir(pathname))==NULL)
        perror("opendir error");

论坛徽章:
2
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:57:09
7 [报告]
发表于 2009-06-06 08:50 |只看该作者

回复 #6 yjh777 的帖子

能解释一下,为什么我不加注释的部分,代码就运行没错呢,是不是就说明这个地方没错啊!
if((dp=opendir(pathname))==NULL)
        perror("opendir error");

楼上能详细说一下原因吗?

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
8 [报告]
发表于 2009-06-06 14:44 |只看该作者
原帖由 liujunwei1234 于 2009-6-5 12:46 发表
这是我照着一本书上的思路,自己写了个统计一个目录下文件的类型和数量的小程序,但是运行时
出现错误double free or corruption,出错的地方在
  

你的程序问题在于对全局变量 pathname 的使用,你一次次的往它的后面添加内容,但是你想过没有你给它分配的空间是否足够?

论坛徽章:
2
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:57:09
9 [报告]
发表于 2009-06-06 15:13 |只看该作者

回复 #8 MMMIX 的帖子

谢谢您的回答!!
你说的这个问题确实存在,但是我的这个程序是不可能溢出的啊,因为运行实例就一层目录,估计路径长度都不超过50个字符。
还有就是为什么把
// if(closedir(dp)<0)
   //     printf("can not close the directory %s",pathname);
   //     这个地方会产生递归调用多次的情况,应在只是在最后一次的时候关闭closedir
这个关闭语句注释起来就没有问题呢? 好像pathname 和 这里的关闭没什么关系吧!

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
10 [报告]
发表于 2009-06-06 15:27 |只看该作者
原帖由 liujunwei1234 于 2009-6-6 15:13 发表
谢谢您的回答!!
你说的这个问题确实存在,但是我的这个程序是不可能溢出的啊,因为运行实例就一层目录,估计路径长度都不超过50个字符。

不管你是超出了一个或是一百个字符,都算是溢出。
还有就是为什么把
// if(closedir(dp)<0)
   //     printf("can not close the directory %s",pathname);
   //     这个地方会产生递归调用多次的情况,应在只是在最后一次的时候关闭closedir
这个关闭语句注释起来就没有问题呢? 好像pathname 和 这里的关闭没什么关系吧!

怎么没有关系呢?pathname 的内存是通过 malloc 动态分配的,如果 opendir 也通过 malloc 动态分配内存,那么自然会通过 closedir 调用 free 释放内存,但是你在 pathname 中写越界了,就会把后面内存分配的 bookkeeping 信息破坏,这样 closedir 调用 free 的时候,glibc 就会警告说:double free or corruption
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP