Мне нужно использовать readdir_r()
, чтобы прочитать содержимое каталога в многопоточной программе. Поскольку размер struct dirent
является файловая система зависит, man readdir_r
рекомендуетВыделение структуры dirent без malloc()
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
?
Для <= C99: Вычислить 'len' в соответствии с вашим ответом, а затем определить' обугленного буфер [Len] '. – alk
@alk: 'char buffer [len]' не обязательно правильно выровнен для 'struct dirent'. Кроме того, разыменование объекта типа 'char' с помощью указателя типа' struct dirent' является неопределенным поведением в соответствии с C. – EOF
Вы это «*, но оно нарушает строгую сглаживание»? Выполняется для 'char'-array? – alk