Mat*_*hew 5 c linux malloc free stack
我在Linux环境中使用C编程语言来读取目录中的文件.我已经包含#include<dirent.h>在我的代码中并使用了该函数readdir().
根据Linux在线页面,它说不会调用free()结果指针到dirent结构,因为它可能被分配在堆栈上.
你能帮我理解它是如何工作的吗?我不明白为什么我们不必删除struct dirent.什么时候删除谁删除它?
以下是我所说的摘录:
成功时,
readdir()返回指向dirent结构的指针.(此结构可以静态分配;不要尝试free(3)它.)如果到达目录流的末尾,NULL则返回并且errno不会更改.如果发生错误,NULL则返回并errno适当设置.
cad*_*luk 10
man readdir 字面上说:
成功时,
readdir()返回指向dirent结构的指针.(此结构可以静态分配;不要尝试free(3).)
(代码格式化程序已添加.)
这意味着它的空间不是在运行时分配的,例如堆栈或空闲存储内存,而是static:它在可执行文件本身,与字符串文字相比,区别在于写入字符串文字是未定义的行为.
想象一下实现是这样的:
struct dirent *readdir(DIR *dirp) {
static struct dirent dir;
/* Fill dir with appropriate values. */
return &dir;
}
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
我不太了解glibc但是线路
dp = (DIRENT_TYPE *) &dirp->data[dirp->offset];
Run Code Online (Sandbox Code Playgroud)
对我们来说似乎是最有趣的.据我所知,这里dirp->data是static数据.
这是什么原因,为什么有折返替代readdir_r和readdir是不可重入.
想象一下两个线程同时执行readdir.两者都会尝试同时填充dir(在所有readdir调用之间共享),导致无序的内存读/写.