在没有malloc的情况下分配struct dirent()
我需要使用readdir_r()
来读取多线程程序中目录的内容。由于struct dirent
的大小依赖于文件系统,man readdir_r
建议在没有malloc的情况下分配struct dirent()
name_max = pathconf(dirpath, _PC_NAME_MAX);
if (name_max == -1) /* Limit not defined, or error */
name_max = 255; /* Take a guess */
len = offsetof(struct dirent, d_name) + name_max + 1;
找到所需要的分配的大小。其分配
entryp = malloc(len);
叫,最后readdir_r()
使用它是这样的:
struct dirent *returned;
readdir_r(DIR*, entryp, &returned);
不过,我想避免调用malloc()
(或任何其他手动内存管理功能)。我想过的
一种方法是
_Alignas(struct dirent) char direntbuf[len];
struct dirent *entryp = (struct dirent*) direntbuf;
这应该给正确对齐的分配,但它违反了严格别名。但是,缓冲区永远不会通过char*
访问,所以最可能的问题是,编译器重新排序通过不同类型访问缓冲区不会发生。
另一种方法可能是alloca()
,它返回void*
,避免严格的别名问题。然而,alloca()
似乎并不能保证malloc()
和朋友的方式一致。总是得到一个对齐的缓冲区,像
void *alloc = alloca(len + _Alignof(struct dirent));
struct dirent *direntbuf = (struct dirent*)((uintptr_t)&((char*)alloc)[_Alignof(struct dirent)]&-_Alignof(struct dirent));
将需要。特别是,需要转换为char *
才能在指针上执行算术运算,并且需要转换为uintptr_t
才能执行二进制&
。这看起来没有比分配char[]
更明确。
在分配struct dirent
时有没有办法避免手动内存管理?
什么有关定义此:
#include <stddef.h> /* For offsetof */
#include <dirent.h>
union U
{
struct dirent de;
char c[offsetof(struct dirent, d_name) + NAME_MAX + 1]; /* NAME_MAX is POSIX. */
};
哇,这实际上非常聪明......我对这种联盟的使用印象深刻。 – EOF
好吧,我会咬。为什么联合而不是结构? – usr2564301
@jongware:结构如何在这里帮助? – alk
的readdir_r函数签名是:
int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
和直接的是这样一个结构:
struct dirent {
ino_t d_ino; /* inode number */
off_t d_off; /* offset to the next dirent */
unsigned short d_reclen; /* length of this record */
unsigned char d_type; /* type of file; not supported
by all file system types */
char d_name[256]; /* filename */
};
你必须通过一个指针readdir_r但你怎么对的dirent结构分配内存完全取决于你。
你可以这样做,并使用堆栈变量。
struct dirent entry = {0};
...
readdir_r(DIR*, &entry, &returned);
对于 alk
@alk:'char buffer [len]'不一定为'struct dirent'正确对齐。另外,根据C. – EOF
,通过类型为“struct dirent”的指针取消引用类型为“char”的对象是未定义的行为。对于char类型数组,您是“*但它违反严格别名*”吗? – alk