Для отладки malloc рассмотрите возможность добавления пробела между вашей управляющей структурой и началом пользовательских данных, а также между концом пользовательских данных и контрольной суммой. Один байт заполнения должен быть нулевым байтом 0x00, поэтому строковые операции останавливаются; подумайте о том, чтобы поставить другой как 0xFF. Если у вас есть фиксированный шаблон и вы заметили, что он изменился, вы знаете, что что-то вышло за пределы границ, но есть большая вероятность, что ваши конфиденциальные управляющие данные не были растоптаны. Если вы используете 16 байтов заполнения по обе стороны от пространства, выделенного пользователю, вы можете дойти до того, что поместите 4 байта нулей с соответствующим выравниванием (следовательно, нулевое 4-байтовое целое число) и, возможно, 0xFFFFFFFF для -1. Кроме того, поскольку вы, вероятно, округлите запрошенный размер до кратного размера вашего базового блока, установите известное значение для байтов, которые не предназначены для использования пользователем, и убедитесь, что они остаются неизменными. Это обнаружит модификации «один сверх выделенной длины» или всего несколько байтов сверх выделенной длины, которые в противном случае могут остаться незамеченными.
Единственным недостатком нулевого байта в заполнении является то, что вы не сможете легко обнаружить операции чтения, которые не останавливаются в конце выделенной памяти при поиске нулевого байта. Вы можете получить представление об этом, если у вас есть альтернативный вариант, который использует заполнение без нулевых байтов.
Другой вариант, который следует рассмотреть, — это попытка полностью отделить ваши управляющие данные от памяти, возвращаемой пользователю. Конечно, полное разделение невозможно, но, по крайней мере, поддерживайте список выделений (с размерами и указателями) отдельно от выделенных блоков. Опять же, это дает вам защиту, помещая ваши драгоценные управляющие данные дальше от неконтролируемых операций по вытаптыванию памяти. Вы не полностью защищены от ошибочных указателей, но вы защищены лучше. (И вы все еще можете обеспечить буферные зоны вокруг выделенного пространства для обнаружения неконтролируемой записи.) Однако этот дизайн заметно отличается от вопроса.
Предполагая, что вы получаете свой блок памяти от 'malloc()', вы должны сделать - примерно:
void *my_malloc(size_t nbytes)
{
size_t reqblocks = (nbytes + sizeof(header) - 1) / sizeof(header);
size_t reqspace = (reqblocks + 2) * sizeof(header) + 2 * sizeof(padding);
void *space = malloc(reqspace);
if (space == 0)
return space;
void *retval = (char *)space + sizeof(header) + sizeof(padding);
header *head = space;
head->next = ...next...;
head->size = nbytes;
...set head padding to chosen value...
...set tail padding to chosen value...
...set gap between nbytes and block boundary to chosen value...
return retval;
}
Осталось интерпретировать...
person
Jonathan Leffler
schedule
10.11.2009