Выравнивание данных (data alighment) общеизвестная проблема в разработке программного обеспечения, если вы программируете встроенные системы или кросс-платформенные приложения. Для примитивных типов, таких как int, char и т. д. компилятор отвечает за выравнивание данных и большую часть времени невидим для разработчика. Большинство программистов имеют представление об этой теме. Если вы этого не знаете обратитесь страницу Википедии. Ограничения и требования к выравниванию обычно меняются для разных архитектур и компиляторов. Применение отступов является хорошим решения этой проблемы. Конечно, вам не нужно вычислять каждый байт в коде, потому что ваш компилятор сделает это за вас.
#pragma pack(1)
struct foo
{
char i;
short j;
int k;
};
Но что, если вам нужно это самим? Здесь для решения этой проблемы используется пользовательская реализация malloc () и free ().
Реализация основана на стандартных функциях malloc () и free (), доступных в вашей системе. Различные системы имеют разные реализации malloc () / free (), но почти все они дают нам то, что нам нужно. Итак, давайте продолжим нашу пользовательскую реализацию. Нам нужен согласованный адрес памяти в соответствии с нашими потребностями. Чтобы написать код, необходимо выполнить следующие шаги:
- Выделите достаточно памяти с помощью malloc (). Достаточно означает запрашиваемый объем памяти клиентом плюс объем памяти, необходимый для хранения небольшой информации. Эта информация включает адрес памяти, возвращенный стандартным malloc (), где сохраняется указатель для free () .
- Вычислите адрес памяти, который может быть использован для хранения данных, следуя правилам выравнивания, необходимым для ваших пользовательских данных.
- И, наконец, верните адрес клиенту.
Ниже приведен код решающий эту проблему
void* aligned_malloc(unsigned int size, int align)
{
/* alignment could not be less then zero */
if (align < 0)
{
return NULL;
}
/* Allocate necessary memory area
* client request - size parameter -
* plus area to store the address
* of the memory returned by standard
* malloc().
*/
void *ptr;
void *p = malloc(size + align - 1 + sizeof(void*));
if (p != NULL)
{
/* Address of the aligned memory according to the align parameter*/
ptr = (void*)(((unsigned int)p + sizeof(void*) + align - 1) & ~(align - 1));
/* store the address of the malloc() above
* at the beginning of our total memory area.
*/
*((void**)ptr - 1) = p;
/* Return the address of aligned memory */
return ptr;
}
return NULL;
}
void aligned_free(void *p)
{
/* Get the address of the memory, stored at the
* start of our total memory area.
*/
void *ptr = *((void**)p - 1);
free(ptr);
}
Одна вещь, которую вы не должны забывать, это использование пользовательской функции «aligned_free()» освобождения памяти, которая была выделена ранее «aligned_malloc()». Следует имейть в виду, что вы не можете использовать стандартный «free()» для памяти, который вы получили, вызывая aligned_malloc(). Это может вызвать сбой.
Оставить комментарий