Вопрос по выравниванию указателя - PullRequest
2 голосов
/ 11 сентября 2009

Я работаю над реализацией пула памяти, и меня немного смущает выравнивание указателей ...

Предположим, что у меня есть пул памяти, который раздает блоки памяти фиксированного размера, в момент создания пула памяти я malloc ((размер) * (количество блоков)). Если то, что распределяется, является объектами, а размер исходит из выравнивания оператора sizeof, это не должно вызывать беспокойства, но если размер неравномерен (он / она хочет по 100 байтных блоков по любой причине), то когда я разделяю порцию, заданную malloc Я бы закончил с указателями без выравнивания. У меня вопрос, должен ли я всегда выравнивать блоки по некоторой границе, и если да, то какой?

Ответы [ 2 ]

3 голосов
/ 11 сентября 2009

Правильное выравнивание, по крайней мере, полезно (с точки зрения производительности) в большинстве реализаций x86 (и какое-то выравнивание фактически является обязательным в других архитектурах). Вы можете запросить (как это делает calloc) пару аргументов, размер элементов в байтах и ​​количество элементов, а не только один (размер в байтах, как это делает malloc); затем вы можете выровнять (округляя размеры блоков) до следующей более высокой степени 2, превышающей размер элемента (но переключайтесь на кратные 16 байт выше 16, не продолжайте удваивать навсегда, как рекомендует и объясняет @derobert! -). Таким образом, если вызывающий просто хочет N байтов без выравнивания или дополнения, он всегда может запросить N элементов по 1 байту каждый (точно так же, как с calloc и по той же причине; -).

2 голосов
/ 11 сентября 2009

X86 будет работать без выравнивания, но при выравнивании данных производительность выше. Выравнивание для type обычно имеет размер sizeof ( type ) максимум до 16 (байтов).

Я написал эту глупую тестовую программу просто для уверенности (предполагается, что malloc знает, что делает), и она возвращает 16 на моей коробке amd64. Возвращает 8 при компиляции в 32-битном режиме:

#include <stdlib.h>
#include <stdio.h>

int main() {
    int i;
    unsigned long used_bits = 0, alignment;

    for (i = 0; i < 1000; ++i) {
        used_bits |= (unsigned long)malloc(1);   /* common sizes */
        used_bits |= (unsigned long)malloc(2);   
        used_bits |= (unsigned long)malloc(4);
        used_bits |= (unsigned long)malloc(8);
        used_bits |= (unsigned long)malloc(16);
        used_bits |= (unsigned long)malloc(437); /* random number */
    }

    alignment = 1;
    while (!(used_bits & alignment)) {
        alignment <<= 1;
    }

    printf("Alignment is: %lu\n", alignment);
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...