2017-01-27 12 views
4

У меня есть функция в C, которая принимает параметр uint8_t *, который должен указывать на 32-разрядную выровненную память. Возможно ли на C или C++ или с помощью макросов какой-либо конкретной платформы добавить некоторое украшение параметру, так что компилятор или компоновщик будут вызывать ошибку во время сборки, если она не выровнена по мере необходимости?Возможно принудительное выравнивание памяти в параметре указателя в C?

Идея здесь в том, что я хочу защитить функцию от неправильного использования другими пользователями (или мне через 6 месяцев). Я знаю, как выровнять материал, который я хочу передать ему. Я бы хотел, чтобы ни один не смог отправить.

Основываясь на this answer, я думаю, что ответ на мой вопрос «нет», это невозможно сделать во время сборки, но это похоже на полезную функцию, поэтому я решил проверить. Моя работа заключается в том, чтобы положить assert((((size_t)ptr) % 4) == 0); в функцию, поэтому, по крайней мере, я мог бы захватить ее во время выполнения при отладке.

По моему опыту, результаты не определены, если вы нанесли несогласованный uint8_t* на uint32_t* на многие встроенные платформы, поэтому я не хочу рассчитывать на «правильный» результат, выходящий в конце. Плюс это используется в системе реального времени, поэтому замедление может быть неприемлемым.

Цитаты приветствуются, если они есть.

+0

Несомненно, не проблема XY? Несогласованный доступ к Intel почти не имеет штрафов, а при строгой архитектуре выравнивания это вызовет SIGBUS. – SergeyA

+1

Как вы ожидаете ошибку в * buld time * для этого? Это потребует довольно многого от компилятора, что если бы я сделал 'uint8_t * sneaky = (uint8_t *) 1; alignmentRequiringFunction (скрытый); '? Или если значение 'sneaky' исходило от' fgets() '? Один из способов, по крайней мере, указать вызывающим абонентам то, что вы ожидаете, - сделать аргумент 'uint32_t *', потому что это означает, что ожидается естественное выравнивание. – unwind

+0

@SergeyA, я не думаю, что это [XY] (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). Я спрашиваю о том, что я думаю о правильном решении. Кроме того, я редактировал вопрос повторно - остальная часть вашего комментария. –

ответ

1

Нет, нет ничего в стандартах C или C++, которые, как я знаю, могут заставить параметр указателя удерживать соответствующее значение.

Чтобы получить память, использовать posix_memalign:

#include <stdlib.h> 

int posix_memalign(void **memptr, size_t alignment, size_t size); 

ОПИСАНИЕ

Функция posix_memalign() выделят байты размера выровненных на границы указанного выравнивания, и возвращает указатель на выделенная память в памяти. Значение выравнивания должно составлять , два кратных sizeof(void *).

После успешного завершения значение, на которое указывает memptr, должно быть , кратным выравниванию.

+0

Полезно знать, но я на встроенной платформе с ограниченными ресурсами, разработка прошивки голого металла для системы реального времени, поэтому мы объявляем все статически. –

+0

@ cp.engr Если вы объявляете свои данные как 'uin32_t' вместо' uint8_t' (* de facto * 'unsigned char', я подозреваю), ваша платформа обеспечивает 32-битное выравнивание? –

+0

Верно, но я пытался отвлечься от необходимости бросить перед передачей параметра. (Действительно, функция нижнего уровня бросает 'uint8_t *' на 'uint32_t *'.) Наверное, я не могу иметь свой торт и съесть его тоже? –

0

Для динамического распределения взгляните на стандарт (начиная с C11) aligned_alloc.

Для статического распределения я не знаю стандартного метода, поэтому он будет зависимым от компилятора. Для gcc, например, проверьте aligned attribute.

+0

Является ли 'aligned_alloc()' частью C++ еще? [Этот вопрос и его ответы] (http://stackoverflow.com/questions/29247065/compiler-cant-find-aligned-alloc-function) несколько месяцев назад. Что касается статического выравнивания, на каждой платформе, на которой я работал, у нее есть требование к выравниванию для типа, такие типы выравниваются должным образом любым хорошим компилятором, поэтому в этом случае я надеюсь, что 'static uint32_t data [...]; 'будет выровнена естественным образом на любом выравниваемом платформе. –

+0

@AndrewHenle: мой ответ был предназначен для C. Для C++ у вас есть другие варианты, такие как ['alignas'] (http://en.cppreference.com/w/cpp/language/alignas), [' aligned_storage'] (http://en.cppreference.com/w/cpp/types/aligned_storage) или размещение нового. Число рейнольдса Естественное выравнивание - кажется разумным ожидать этого, но я не уверен, что вы можете положиться на такое поведение, поэтому консультирование по документации вашей платформы, вероятно, является хорошей идеей. –

 Смежные вопросы

  • Нет связанных вопросов^_^