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

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,导致无序的内存读/写.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值