从函数readdir释放(删除)已分配的内存

我在Linux环境中使用C编程语言来读取目录中的文件.我包括#include< dirent.h>在我的代码中,我正在使用函数readdir().

根据Linux在线页面,它说不会在结果指向dirent结构的地方调用free(),因为它可能被分配在堆栈上.

你能帮我理解它是如何工作的吗?我不明白为什么我们不必删除struct dirent.什么时候删除谁删除它?

Here是我所说的摘录:

On success,readdir() returns a pointer to a dirent structure. (This structure may be statically allocated; do not attempt to free(3) it.) If the end of the directory stream is reached,NULL is returned and errno is not changed. If an error occurs,NULL is returned and errno is set appropriately.

最佳答案
man readdir字面上说:

On success,readdir() returns a pointer to a dirent structure.
(This structure may be statically allocated; do not attempt to
free(3) it.)

(代码格式化程序已添加.)

这意味着它的空间不是在运行时分配的,例如堆栈或空闲存储内存,而是静态的:它在可执行文件本身,与字符串文字相当,区别在于写入字符串文字是未定义的行为.

想象一下实现是这样的:

struct dirent *readdir(DIR *dirp) {
    static struct dirent dir;

    /* Fill dir with appropriate values. */

    return &dir;
}

dir在这里静态分配.返回它的地址没有错,因为它存在于程序的整个运行时间中.

这是我的glibc 2.22实现上readdir的实际源代码(路径为/sysdeps/posix/readdir.c):

DIRENT_TYPE *
__READDIR (DIR *dirp)
{
  DIRENT_TYPE *dp;
  int saved_errno = errno;

#if IS_IN (libc)
  __libc_lock_lock (dirp->lock);
#endif

  do
    {
      size_t reclen;

      if (dirp->offset >= dirp->size)
    {
      /* We've emptied out our buffer.  Refill it.  */

      size_t maxread;
      ssize_t bytes;

#ifndef _DIRENT_HAVE_D_RECLEN
      /* Fixed-size struct; must read one at a time (see below).  */
      maxread = sizeof *dp;
#else
      maxread = dirp->allocation;
#endif

      bytes = __GETDENTS (dirp->fd,dirp->data,maxread);
      if (bytes <= 0)
        {
          /* On some systems getdents fails with ENOENT when the
         open directory has been rmdir'd already.  POSIX.1
         requires that we treat this condition like normal EOF.  */
          if (bytes < 0 && errno == ENOENT)
        bytes = 0;

          /* Don't modifiy errno when reaching EOF.  */
          if (bytes == 0)
        __set_errno (saved_errno);
          dp = NULL;
          break;
        }
      dirp->size = (size_t) bytes;

      /* Reset the offset into the buffer.  */
      dirp->offset = 0;
    }

      dp = (DIRENT_TYPE *) &dirp->data[dirp->offset];

#ifdef _DIRENT_HAVE_D_RECLEN
      reclen = dp->d_reclen;
#else
      /* The only version of `struct dirent*' that lacks `d_reclen'
     is fixed-size.  */
      assert (sizeof dp->d_name > 1);
      reclen = sizeof *dp;
      /* The name is not terminated if it is the largest possible size.
     Clobber the following byte to ensure proper null termination.  We
     read jst one entry at a time above so we know that byte will not
     be used later.  */
      dp->d_name[sizeof dp->d_name] = '\0';
#endif

      dirp->offset += reclen;

#ifdef _DIRENT_HAVE_D_OFF
      dirp->filepos = dp->d_off;
#else
      dirp->filepos += reclen;
#endif

      /* Skip deleted files.  */
    } while (dp->d_ino == 0);

#if IS_IN (libc)
  __libc_lock_unlock (dirp->lock);
#endif

  return dp;
}

我不太了解glibc但是线路

dp = (DIRENT_TYPE *) &dirp->data[dirp->offset];

对我们来说似乎是最有趣的. dirp->数据就是这里的静态数据,据我所知.

这就是为什么有可重入的替代readdir_r和readdir不可重入的原因.
想象两个线程同时执行readdir.两者都会尝试同时填充所有readdir调用之间共享的dir,导致无序的内存读/写.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


查找全部容器的日志文件 $ sudo find /var/lib/docker/containers -name *.log 查看日志位置 $ docker inspect --format=&#39;{{.LogPath}}&#39; &lt;container_name&gt; 实时查询内容 $
Linux日志文件中列属性的详细解析
在Linux系统中没有duf命令,如何有效地管理磁盘空间?
深入探讨EncryptPad在Linux操作系统中的功能和优势
原理和应用场景:Linux中ttyload工具的工作原理和实际用途
深度解析SELinux的三种策略类型
评估Linux系统性能的ttyload工具使用效果
分享在Linux系统中检测SSH版本的方法
介绍Linux平台上的数据加密工具EncryptPad
在Linux系统中,如何查看和诊断块设备信息?
在Linux环境下如何查看块设备信息?
探索Linux操作系统下的数据加密工具EncryptPad
学会在Linux系统中查看硬盘信息
分析SELinux:原理与实践
掌握SELinux策略类别
技巧:有效解读和管理Linux日志文件
查看Linux系统中的所有用户
了解Linux系统中各种不同类型的日志文件
深入理解Linux PS命令
方法:在Linux操作系统中查看用户