LINUX.ORG.RU

malloc, returned value alignment


0

0

man malloc: The pointer returned if the allocation succeeds shall be suitably aligned so that it may be assigned to a pointer to any type of object and then used to access such an object in the space allocated (until the space is explicitly freed or reallocated).

А как узнать, по какой границе может быть выровнен любой возможный тип? Это ведь фиксированное число. Если считать это число равным выравниванию long long-а, это будет верно? (например на 32-битной это 8)

anonymous

В идеале хотелось бы портабельно узнать это значение.

anonymous
()

непонятно что значит портабельность,
перенос на другую машину или другую ОС,
советую почитать info libc:
memalign
posix_memalign
и т.д. и т.п.

anonymous
()

Гм. А зачем нужно такое извращение?

Я не думаю, что есть реально портабельный (читай - описанный в POSIX или стандарте языка C).

Если нужны заведомо выровненные участки памяти - memalign, как уже сказали. А так, я думаю, что на большинстве систем это что-то в духе sizeof(void *).

anonymous
()

Это зависит от архитектуры, а не размеров каких-либо типов. На IA32 выравнивание с точки зрения корректности кода безразлично, поскольку любое корректно (хотя эффективно обращение только к выровненным данным). Некоторые процессоры (например, DEC Alpha) просто не смогут разыменовать кривой указатель. В случае с Linux, правда, это никак не выразится, т.к. Linux большинство случаев обработает в ядре (разберет инструкцию и выполнит ее в ядре), правда, будет это не просто медленно, а страшно медленно.

anonymous
()

> непонятно что значит портабельность,
> перенос на другую машину или другую ОС,

ОС = windows, unix
машины.. чем больше тем лучше :)

Вообще есть такое понятие как идеальный код, который работает на любой архитектуре. По крайней мере должен работать по стандарту :)


> советую почитать info libc:
> memalign
> posix_memalign

Это хорошо, но не совсем то.

> Гм. А зачем нужно такое извращение?

Чтобы знать, как выравнивать указатель, для написания аналога malloc-а.

> А так, я думаю, что на большинстве систем это что-то в духе sizeof(void *).

Ну вот я сейчас пишу в венде - там void* выравнивается по 4 байта, а long long по 8. В линуксе правда всё по 4 байта. (IA-32)


> Это зависит от архитектуры, а не размеров каких-либо типов.

Это понятно.. Но задача остаётся.

Например есть такая штука:
template <typename T>
struct T_char {
T t;
char c;
};
// returns alignment of the type T
#define STRIDEOF(T) \
(sizeof(T_char<T>) > sizeof(T) ? sizeof(T_char<T>) - sizeof(T) : sizeof(T))

STRIDEOF гарантированно возвращает выравнивание, по которому можно выравнивать заданный тип. А как определить максимальное выравнивание.

Пока остановился на STRIDEOF(long long) ...

anonymous
()
Ответ на: комментарий от anonymous

я тоже когда-то думал над этим -- строго по стандарту Си это вроде не сделать. На мой взгляд -- самый большое выравнивание может требовать double.

dilmah ★★★★★
()
Ответ на: комментарий от anonymous

> STRIDEOF гарантированно возвращает выравнивание, по которому можно выравнивать заданный тип. А как определить максимальное выравнивание.

Обычно в таких случаях делают union из всех приходящих в голову типов, и уже над ним каким-нибудь способом издеваются.

anonymous
()
Ответ на: комментарий от anonymous

>А как определить максимальное выравнивание. 


В смысле минимальное?

configure

ARCH=`uname -m`
if [ `echo $ARCH| awk /i.x86/` ]; then
   CONFIG_ALIGNMENT=1
   CONFIG_PREFFERED_ALIGNMENT=4
fi

if [ "$ARCH"=="alpha" ]; then
   CONFIG_ALIGNMENT=4
   CONFIG_PREFFERED_ALIGNMENT=4
fi

...

echo "#define CONFIG_ALIGNMENT $CONFIG_ALIGNMENT" >> config.h
echo "#define CONFIG_PREFFERED_ALIGNMENT $CONFIG_PREFFERED_ALIGNMENT" >> config.h

anonymous
()

Понятно, всем спасибо

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.