Free (delete) allocated memory from readdir function

I use the C programming language in Linux to read files in a directory. I have included #include<dirent.h>in my code and use the function readdir().

According to the Linux page on the Internet, it says that it does not result free()in a pointer to the structure dirent, because it can be allocated on the stack.

Can you help me understand how this works? I do not understand why we did not need to delete struct dirent. When does it go away and who removes it?

Here is the excerpt I am talking about:

If successful, readdir()returns a pointer to the structure dirent. (This structure can be statically distributed, do not try it free(3).) If the end of the directory stream is reached, it returns NULLand errnodoes not change. If an error occurs, it is returned NULLand errnoset accordingly.

+4
source share
5 answers

man readdir literally says:

If successful, readdir()returns a pointer to the dirent structure. (This structure can be statically distributed, do not try free(3)it.)

(Added code formatting.)

, , , static: itsself, , undefined .

, :

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

    /* Fill dir with appropriate values. */

    return &dir;
}

dir . , .

readdir glibc 2.22 ( /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->data - static , .


, readdir_r readdir .
, readdir. dir, readdir, , / .

+10

, , , struct dirent . free() .

free() [m ] [c] [re] alloc(), . ( )

+3

free() , malloc() family. , .

OTOH, (. ) . , .

+1

/ , readdir(). , , , . , , , . . readdir_r(), , , .

closedir() DIR *, , opendir().

+1

struct dirent DIR. readdir() DIR ( readdir() DIR) closedir().

, readdir() . , , -, struct dirent readdir(). readdir_r() , NAME_MAX , readdir_r() , .

readdir_r() http://austingroupbugs.net/view.php?id=696.

0
source

Source: https://habr.com/ru/post/1622373/


All Articles