Мне нужно использовать readdir_r()
для чтения содержимого каталога в многопоточной программе. Поскольку размер struct dirent
зависит от файловой системы, man readdir_r
рекомендует
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
?
len
в соответствии с вашим ответом, затем определитеchar buffer[len]
. - person alk   schedule 09.05.2015char buffer[len]
не обязательно правильно выровнен дляstruct dirent
. Кроме того, разыменование объекта типаchar
с помощью указателя типаstruct dirent
является неопределенным поведением согласно C. - person EOF   schedule 09.05.2015char
-массива? - person alk   schedule 09.05.2015char
, это здесь не поможет. - person EOF   schedule 09.05.2015