Linux C编程 打开目录后,不使用closedir()函数,会有什么样的影响?

在这里插入图片描述

翻博客的时候看到一个有意思的问题,所以就手动研究一下这个问题,
我觉得这个问题中描述的情况会导致内存泄漏内存泄漏是什么

(系统是Ubuntu 18.04的,可以直接去/usr/include找头文件中的定义)
1.
保险起见,我觉得应该去dirent.h看一看,毕竟函数是在这里定义的
嗯,opendir()会返回一个目录流

在这里插入图片描述
2.
再看看closedir()
在这里插入图片描述
3.
从函数声明以及头文件的注释这里并没有看到什么,
想起以前软工的学长给我推荐的一个检查内存泄露的分析工具Valgrind(Linux性能分析工具Valgrid),不妨拿出来玩一玩。

手头有一个现成的程序,我把其中的closedir()注释掉(line74),然后用valgrind检查.
#include <stdio.h>          //perror()
#include <stdlib.h>
#include <string.h>
#include <errno.h>          //strerror()
#include <sys/types.h>      //opendir(),readdir() ,struct stat
#include <dirent.h>         //opendir(), readdir()
#include <sys/stat.h>       //struct stat , stat()
#include <unistd.h>        //stat()

//如果DEBUG为true,则输出函数名称和行号,然后输出您想要打印的内容
//注意  这个报错宏并不会退出进程,你可以使用exit(-1) 来手动退出进程
int DEBUG=1;
#define DBGLOG(format, ...) if(DEBUG){ fprintf(stderr, "%s -- %d -- ", __FUNCTION__, __LINE__); fprintf(stderr, format, ##__VA_ARGS__);}


void do_ls(char* dirname);          //访问各个目录
void do_stat(char* filename);       //获取各个文件信息
void show_file_info(char * filename,struct stat *file_info);//展示单个文件的信息

int main(int argc,char **argv)
{
    if(argc==1){

        do_ls(".");

    }else {

    while(argc=argc-1){
        printf("%s:\n",*++argv);
        chdir(*argv);       //切换工作目录到对应的路径 如果argv并非是目录文件,也可以这么做
        do_ls(*argv);
        chdir("");          //切换工作目录到当前目录 这一步是必要的吗
    }

    }

    return 0;
}

void do_ls(char* dirname){//访问各个目录

    DIR * dir_ptr;
    struct dirent *dirent_ptr;
    /********************************
    struct dirent
    {
       long d_ino;                  //inode number 索引节点号
       off_t d_off;                 //offset to this dirent 在目录文件中的偏移
       unsigned short d_reclen;     //length of this d_name 文件名长
       unsigned char d_type;        //the type of d_name 文件类型
       char d_name [NAME_MAX+1];    //file name (null-terminated) 文件名,最长255字符
    }
    ********************************/

    if( (dir_ptr=opendir(dirname))==NULL ){

            //如果不是目录文件,就会报错,并且直接进行do-stat()处理
            DBGLOG("Cannot open %s , not a directory, treat as a file shown below:\n",dirname);
            //这里并不退出进程 ,因为在ls命令中实参可以使用文件名
            do_stat(dirname);

    }else{  //是目录文件,需要用readdir()

        while( (dirent_ptr=readdir(dir_ptr))!=NULL ){

            do_stat(dirent_ptr->d_name);

        }



    }

  // if( closedir(dir_ptr)==-1 ){    //关闭目录句柄失败

        //DBGLOG("Closedir %s Error: %s\n",dirname,strerror(errno));
  //
        //exit(-1);
  //  }

}

void do_stat(char* filename){//获取各个文件信息

    struct stat file_info;
    /********************************
    struct stat {

        mode_t     st_mode;       //文件对应的模式,文件,目录等

        ino_t      st_ino;       //inode节点号

        dev_t      st_dev;        //设备号码

        dev_t      st_rdev;       //特殊设备号码

        nlink_t    st_nlink;      //文件的连接数

        uid_t      st_uid;        //文件所有者

        gid_t      st_gid;        //文件所有者对应的组

        off_t      st_size;       //普通文件,对应的文件字节数

        time_t     st_atime;      //文件最后被访问的时间

        time_t     st_mtime;      //文件内容最后被修改的时间

        time_t     st_ctime;      //文件状态改变时间

        blksize_t st_blksize;    //文件内容对应的块大小

        blkcnt_t   st_blocks;     //伟建内容对应的块数量

      };
    ********************************/

    if( stat(filename,&file_info)==-1 ){//读文件信息失败

        DBGLOG("Get %s file_info error \n",filename);

        exit(-1);


    }else{//读文件信息成功

        show_file_info(filename,&file_info);

    }



}

void show_file_info(char * filename,struct stat *file_info){//展示单个文件的信息

    printf("show_file_info: %s ;\n",filename);

}


用valgrind检查以下有没有内存泄露

在这里插入图片描述

好家伙,直接内存泄漏32,816字节,就因为没有用closedir()关掉DIR流

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux C 语言中,使用系统函数复制目录需要使用递归的方式遍历目录树,并对每个文件进行复制。下面是一个简单的示例程序: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <sys/types.h> #include <sys/stat.h> #include <dirent.h> #define BUFFER_SIZE 1024 void copy_file(const char *src, const char *dst) { char buffer[BUFFER_SIZE]; size_t nread; FILE *fp_src = fopen(src, "rb"); if (fp_src == NULL) { perror("fopen"); exit(1); } FILE *fp_dst = fopen(dst, "wb"); if (fp_dst == NULL) { perror("fopen"); exit(1); } while ((nread = fread(buffer, 1, sizeof(buffer), fp_src)) > 0) { fwrite(buffer, 1, nread, fp_dst); } fclose(fp_src); fclose(fp_dst); } void copy_dir(const char *src, const char *dst) { DIR *dir = opendir(src); if (dir == NULL) { perror("opendir"); exit(1); } char src_path[BUFFER_SIZE], dst_path[BUFFER_SIZE]; struct dirent *entry; struct stat statbuf; while ((entry = readdir(dir)) != NULL) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { continue; } snprintf(src_path, sizeof(src_path), "%s/%s", src, entry->d_name); snprintf(dst_path, sizeof(dst_path), "%s/%s", dst, entry->d_name); if (lstat(src_path, &statbuf) == -1) { perror("lstat"); exit(1); } if (S_ISREG(statbuf.st_mode)) { copy_file(src_path, dst_path); } else if (S_ISDIR(statbuf.st_mode)) { if (mkdir(dst_path, statbuf.st_mode & 0777) == -1 && errno != EEXIST) { perror("mkdir"); exit(1); } copy_dir(src_path, dst_path); } else { fprintf(stderr, "Unsupported file type: %s\n", src_path); exit(1); } } closedir(dir); } int main(int argc, char *argv[]) { if (argc != 3) { fprintf(stderr, "Usage: %s <source> <destination>\n", argv[0]); exit(1); } if (mkdir(argv[2], 0777) == -1 && errno != EEXIST) { perror("mkdir"); exit(1); } copy_dir(argv[1], argv[2]); return 0; } ``` 这个程序的使用方法是: ``` $ ./copydir <source> <destination> ``` 其中 `<source>` 是源目录的路径,`<destination>` 是目标目录的路径。 程序首先检查命令行参数的个数是否正确,如果不正确则输出用法信息并退出。然后创建目标目录,如果目录创建失败则输出错误信息并退出。接下来,程序使用递归的方式遍历源目录中的文件,并将它们复制到目标目录中。如果遇到普通文件,则调用 `copy_file` 函数进行复制;如果遇到子目录,则递归调用 `copy_dir` 函数进行复制。 需要注意的是,在复制目录时,目标目录必须事先存在。如果目标目录不存在,则需要先创建目标目录。此外,如果遇到目录中存在软链接等非普通文件类型,则需要根据实际情况进行处理。 如果要使用标准库来粘贴目录到其他目录,可以使用 `system` 函数调用 `cp` 命令来实现。例如: ```c #include <stdlib.h> int main() { system("cp -r /path/to/source /path/to/destination"); return 0; } ``` 这个程序的作用是将 `/path/to/source` 目录复制到 `/path/to/destination` 目录中。需要注意的是,在使用 `system` 函数调用命令时,需要特别注意命令中可能包含的特殊字符,如空格、单引号、双引号等。这些特殊字符可能导致命令执行出错。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值