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

前端之家收集整理的这篇文章主要介绍了从函数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,导致无序的内存读/写.

原文链接:https://www.f2er.com/linux/440540.html

猜你在找的Linux相关文章