В исходном коде программы встретил такую реализацию оператора new: void *__cdecl operator new(unsigned int size) { return (char *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size+32)+16; } Зачем +32 и +16 ?
Используется например так: Textures = new unsigned char[number*256*256]; С виду ничего необычного. delete имеет такую реализацию: void __cdecl operator delete(void *p) { HeapFree(GetProcessHeap(), 0, (char *) p-16); }
Это не использование, а выделение памяти В твоем примере выделится блок памяти такого вида: <16 bytes><data><16 bytes> data - массив размера number*256*256 байт New возвращает адрес массива data. В дополнительных блоках перед и после массива, видимо, хранится какая-то служебная инфа (например, размер массива, размеры текстур, bits per pixel, etc.).
и 16 байт до и после блока могут служить защитой от кривых рук (выход за границы блока в коде) например
infern0 Видимо, подсмотрел где-то. Смысл такого? В дебаге хип и так следит за выходом за границы. А здесь если выйдешь, то не узнаешь об этом. Надо устранять причину выхода, а не обходить её.
rmn В дополнительных блоках перед и после массива, видимо, хранится какая-то служебная инфа (например, размер массива, размеры текстур, bits per pixel, etc.). Я привел только один пример использования оператора. Никакого обращения к этим "резервным" байтам нет. Так же просмотрел несколько других методов в которых используется оператор, указатель и... ничего. Обычное обращение к членам массивам при помощи индексирования. Зачем нужна такая симметрия? Выделить пару байтов можно и с самого начала. А тут именно по центру. Просмотрю другие констукторы объектов, если что найду сообщу.
IceStudent Выход за пределы возможен при обработке строк некоторыми алгоритмами, использующими для ускорения работы подвордную обработку символов в строке. Может и здесь нечто подобное. Это изначально закладывается в алгоритм (возможность выхода например за пределы строки) и кривизна рук здесь ни при чём. Правда непонятно, почему выделяется 16 байт. Может, обработка как-то связана с размерностью большей, чем 4 байта (варианты с mmx, fpu)
cresta Ну, одно дело выделить память с запасом под конкретный алгоритм, и другое - делать это всегда.
Упустил один момент. Если посмотреть на схему <16 bytes><data><16 bytes> то участок <data><16 bytes> заполняется в цикле: colormap=new unsigned int[256]; unsigned char r,g,b; for(int i=0; i<256; i++) { r = 255-(unsigned char)((float)(i)*v.x); g = 255-(unsigned char)((float)(i)*v.y); b = 255-(unsigned char)((float)(i)*v.z); colormap = 0x00000000 + (r<<16) + (g<<8) + b; } Аналогичная методика заполнения участка памяти, выделенного хипом, встречается в других местах исходного кода проекта. Требуемое место для данных предварительно(new) выделяется немного(на 16 байт) больше.
IceStudent Например я бы не стал делать две разные модификации new - одну для обычного случая, другую с запасом 32 байта. Сделал бы ту, которая +32 и использовал бы во всех случаях. 32 байта - небольшая плата за то, чтобы не возиться с двумя разными new.
В MSDN, кстати, рекомендуется перекрыть new и поставить этот оператор на собственный аллокатор (HeapCreate()/HeapAlloc()), это не даст смешивать аллокацию объектов С++ с другими аллокациями, ускоряя программу в целом. Вообще, советуют использовать любое количество Heap объектов, и по-моему: это оправдано.
Я говорю про локализацию выделений памяти. Например, есть некий документ и на выделение его структур надо бы поставить свой собственный heap. С++ объекты - в другой heap. Все коллекции: листы, массивы и т.п. - ещё heap. Пример: загружено сотня документов и надо изменить один из них. Изменение затронет только heap этого документа. Если же все сто документов используют один heap - неоптимальность такого подхода очевидна. Странно, не могу найти в MSDN эту статейку про new.
Хм, мне не очень очевидна, хотелось бы узнать, почему не оптимально. Отдельной группе объектов не так легко назначить свой аллокатор. Если в stl ещё используется стандартный интерфейс аллокатора, то прикрутить его к своим существующим объектам не так просто.