scandir函数的研究【笔记】

简介: 以下是本人的学习笔记,代码并非原创,均摘自官方源码,贴出来仅供学习记录用 scandir 的使用要注意内存泄漏的问题 scandir函数实现: vi ./uClibc-0.9.33.2/libc/misc/dirent/scandir.

以下是本人的学习笔记,代码并非原创,均摘自官方源码,贴出来仅供学习记录用

scandir 的使用要注意内存泄漏的问题

scandir函数实现:

vi ./uClibc-0.9.33.2/libc/misc/dirent/scandir.c

/*
 * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
 *
 * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
 */

#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include "dirstream.h"

int scandir(const char *dir, struct dirent ***namelist,
    int (*selector) (const struct dirent *),
    int (*compar) (const struct dirent **, const struct dirent **))
{
    DIR *dp = opendir (dir);
    struct dirent *current;
    struct dirent **names = NULL;
    size_t names_size = 0, pos;
    int save;

    if (dp == NULL)
    return -1;

    save = errno;
    __set_errno (0);

    pos = 0;
    while ((current = readdir (dp)) != NULL) {
    int use_it = selector == NULL;

    if (! use_it)
    {
        use_it = (*selector) (current);
        /* The selector function might have changed errno.
         * It was zero before and it need to be again to make
         * the latter tests work.  */
        if (! use_it)
        __set_errno (0);
    }
    if (use_it)
    {
        struct dirent *vnew;
        size_t dsize;

        /* Ignore errors from selector or readdir */
        __set_errno (0);

        if (unlikely(pos == names_size))
        {
        struct dirent **new;
        if (names_size == 0)
            names_size = 10;
        else
            names_size *= 2;
        new = (struct dirent **) realloc (names,
                    names_size * sizeof (struct dirent *));
        if (new == NULL)
            break;
        names = new;
        }

        dsize = &current->d_name[_D_ALLOC_NAMLEN(current)] - (char*)current;
        vnew = (struct dirent *) malloc (dsize);
        if (vnew == NULL)
        break;

        names[pos++] = (struct dirent *) memcpy (vnew, current, dsize);
    }
    }

    if (unlikely(errno != 0))
    {
    save = errno;
    closedir (dp);
    while (pos > 0)
        free (names[--pos]);
    free (names);
    __set_errno (save);
    return -1;
    }

    closedir (dp);
    __set_errno (save);

    /* Sort the list if we have a comparison function to sort with.  */
    if (compar != NULL)
    qsort (names, pos, sizeof (struct dirent *), (comparison_fn_t) compar);
    *namelist = names;
    return pos;
}

例子参考1:

vi ./uClibc-0.9.33.2/test/stdlib/qsort.c

#include <stdio.h>
#include <dirent.h>
#include <stdlib.h>
#include <unistd.h>

static int select_files(const struct dirent *dirbuf)
{
    if (dirbuf->d_name[0] == '.')
        return 0;
    else
        return 1;
}

int main(void)
{
    struct dirent **array;
    struct dirent *dirbuf;

    int i, numdir;

    chdir("/");
    numdir = scandir(".", &array, select_files, NULL);
    printf("\nGot %d entries from scandir().\n", numdir);
    for (i = 0; i < numdir; ++i) {
        dirbuf = array[i];
        printf("[%d] %s\n", i, dirbuf->d_name);
        free(array[i]);
    }
    free(array);
    numdir = scandir(".", &array, select_files, alphasort);
    printf("\nGot %d entries from scandir() using alphasort().\n", numdir);
    for (i = 0; i < numdir; ++i) {
        dirbuf = array[i];
        printf("[%d] %s\n", i, dirbuf->d_name);
    }
    printf("\nCalling qsort()\n");
    /* Even though some manpages say that alphasort should be
     * int alphasort(const void *a, const void *b),
     * in reality glibc and uclibc have const struct dirent**
     * instead of const void*.
     * Therefore we get a warning here unless we use a cast,
     * which makes people think that alphasort prototype
     * needs to be fixed in uclibc headers.
     */
    qsort(array, numdir, sizeof(struct dirent *), (void*) alphasort);
    for (i = 0; i < numdir; ++i) {
        dirbuf = array[i];
        printf("[%d] %s\n", i, dirbuf->d_name);
        free(array[i]);
    }
    free(array);
    return (0);
}

例子参考2:

man scandir

EXAMPLE
       #define _SVID_SOURCE
       /* print files in current directory in reverse order */
       #include <dirent.h>

       int
       main(void)
       {
           struct dirent **namelist;
           int n;

           n = scandir(".", &namelist, NULL, alphasort);
           if (n < 0)
               perror("scandir");
           else {
               while (n--) {
                   printf("%s\n", namelist[n]->d_name);
                   free(namelist[n]);
               }
               free(namelist);
           }
       }

 

【作者】 张昺华
【新浪微博】 张昺华--sky
【twitter】 @sky2030_
【facebook】 张昺华 zhangbinghua
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
目录
相关文章
|
5月前
|
C语言 C++
技术笔记:strtol函数
技术笔记:strtol函数
46 0
|
6月前
|
机器学习/深度学习 人工智能 资源调度
AI【基础 01】神经网络基础知识(不断进行补充整理)
神经网络基础知识(不断进行补充整理)
119 2
|
机器学习/深度学习 计算机视觉
可解释机器学习 - 李宏毅笔记
可解释机器学习 - 李宏毅笔记
|
搜索推荐 数据库
【科技论文的写作程序及方法】
【科技论文的写作程序及方法】
129 0
|
机器学习/深度学习 自然语言处理 算法
12 月机器学习新书:《可解释机器学习方法的局限》,免费下载!
12 月机器学习新书:《可解释机器学习方法的局限》,免费下载!
183 0
12 月机器学习新书:《可解释机器学习方法的局限》,免费下载!
|
算法 机器学习/深度学习 BI
干货 | 关于机器学习的知识点,全在这篇文章里了
本文为大家介绍机器学习的魅力与可怕。
3896 0
|
机器学习/深度学习 算法
我是怎么用机器学习技术找到女票的
机器学习在我们生活中的用处有多大,就不用我们多说了,大到医疗诊断,小到手机应用,机器学习都应用的风风火火。但是用机器学习帮自己在学校找对象,你听说过吗?
3829 0
|
机器学习/深度学习 算法
机器学习--1. 疑惑及个人见解
最近一段时间,在学习机器学习,学习过程中遇到了一些疑惑,再次记录下来,一方面梳理自己的思路,另一方面给大家分享避免踩坑,欢迎argue。。。
274 0
|
机器学习/深度学习 人工智能 算法
|
机器学习/深度学习 人工智能 算法
五位专家跟你讲讲为啥Python更适合做AI/机器学习
为什么Python会在这股深度学习浪潮中成为编程语言的头牌?听听大牛如何解释吧!
4897 0