Перегрузка new

Тема в разделе "WASM.WIN32", создана пользователем Tiro, 1 сен 2006.

  1. Tiro

    Tiro New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2006
    Сообщения:
    49
    Адрес:
    Russia
    В исходном коде программы встретил такую реализацию оператора new:

    void *__cdecl operator new(unsigned int size)
    {
    return (char *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size+32)+16;
    }

    Зачем +32 и +16 ?
     
  2. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    16 байт до данных и, видимо, 16 после данных. Как используется?
     
  3. Tiro

    Tiro New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2006
    Сообщения:
    49
    Адрес:
    Russia
    Используется например так:
    Textures = new unsigned char[number*256*256];
    С виду ничего необычного.

    delete имеет такую реализацию:
    void __cdecl operator delete(void *p)
    {
    HeapFree(GetProcessHeap(), 0, (char *) p-16);
    }
     
  4. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.348
    Это не использование, а выделение памяти :)

    В твоем примере выделится блок памяти такого вида:

    <16 bytes><data><16 bytes>

    data - массив размера number*256*256 байт

    New возвращает адрес массива data. В дополнительных блоках перед и после массива, видимо, хранится какая-то служебная инфа (например, размер массива, размеры текстур, bits per pixel, etc.).
     
  5. infern0

    infern0 New Member

    Публикаций:
    0
    Регистрация:
    7 окт 2003
    Сообщения:
    811
    Адрес:
    Russia
    и 16 байт до и после блока могут служить защитой от кривых рук (выход за границы блока в коде) например
     
  6. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    infern0
    Видимо, подсмотрел где-то. Смысл такого? В дебаге хип и так следит за выходом за границы. А здесь если выйдешь, то не узнаешь об этом. Надо устранять причину выхода, а не обходить её.
     
  7. Tiro

    Tiro New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2006
    Сообщения:
    49
    Адрес:
    Russia
    rmn
    В дополнительных блоках перед и после массива, видимо, хранится какая-то служебная инфа (например, размер массива, размеры текстур, bits per pixel, etc.).

    Я привел только один пример использования оператора. Никакого обращения к этим "резервным" байтам нет. Так же просмотрел несколько других методов в которых используется оператор, указатель и... ничего. Обычное обращение к членам массивам при помощи индексирования.
    Зачем нужна такая симметрия? Выделить пару байтов можно и с самого начала. А тут
    именно по центру.
    Просмотрю другие констукторы объектов, если что найду сообщу.
     
  8. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    IceStudent
    Выход за пределы возможен при обработке строк некоторыми алгоритмами, использующими для ускорения работы подвордную обработку символов в строке. Может и здесь нечто подобное. Это изначально закладывается в алгоритм (возможность выхода например за пределы строки) и кривизна рук здесь ни при чём. Правда непонятно, почему выделяется 16 байт. Может, обработка как-то связана с размерностью большей, чем 4 байта (варианты с mmx, fpu)
     
  9. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    cresta
    Ну, одно дело выделить память с запасом под конкретный алгоритм, и другое - делать это всегда.
     
  10. Tiro

    Tiro New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2006
    Сообщения:
    49
    Адрес:
    Russia
    Упустил один момент. Если посмотреть на схему <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 байт) больше.
     
  11. Tiro

    Tiro New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2006
    Сообщения:
    49
    Адрес:
    Russia
    Немного ошибся в расчете. Схема <16 bytes><data><16 bytes> действительно правильна.
     
  12. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    IceStudent
    Например я бы не стал делать две разные модификации new - одну для обычного случая, другую с запасом 32 байта. Сделал бы ту, которая +32 и использовал бы во всех случаях. 32 байта - небольшая плата за то, чтобы не возиться с двумя разными new.
     
  13. infern0

    infern0 New Member

    Публикаций:
    0
    Регистрация:
    7 окт 2003
    Сообщения:
    811
    Адрес:
    Russia
    особенно если в итоге забыть вызвать нужный new...
     
  14. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    cresta
    Вообще, по правилам не рекомендуется перекрывать глобальные операторы - это стиль кода.
     
  15. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Ну дык это же не я перекрыл стандартный new :))) Я стандартными вообще стараюсь не пользоваться.
     
  16. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    cresta
    Я в ответ на
    :)
     
  17. AsmGuru62

    AsmGuru62 Member

    Публикаций:
    0
    Регистрация:
    12 сен 2002
    Сообщения:
    689
    Адрес:
    Toronto
    В MSDN, кстати, рекомендуется перекрыть new и поставить этот оператор на собственный аллокатор (HeapCreate()/HeapAlloc()), это не даст смешивать аллокацию объектов С++ с другими аллокациями, ускоряя программу в целом. Вообще, советуют использовать любое количество Heap объектов, и по-моему: это оправдано.
     
  18. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    Интересно, с какими? Мало кто переопределяет new для своих объектов. И где именно рекомендуется?
     
  19. AsmGuru62

    AsmGuru62 Member

    Публикаций:
    0
    Регистрация:
    12 сен 2002
    Сообщения:
    689
    Адрес:
    Toronto
    Я говорю про локализацию выделений памяти. Например, есть некий документ и на выделение его структур надо бы поставить свой собственный heap. С++ объекты - в другой heap. Все коллекции: листы, массивы и т.п. - ещё heap.

    Пример: загружено сотня документов и надо изменить один из них. Изменение затронет только heap этого документа. Если же все сто документов используют один heap - неоптимальность такого подхода очевидна.

    Странно, не могу найти в MSDN эту статейку про new.
     
  20. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    Хм, мне не очень очевидна, хотелось бы узнать, почему не оптимально.

    Отдельной группе объектов не так легко назначить свой аллокатор. Если в stl ещё используется стандартный интерфейс аллокатора, то прикрутить его к своим существующим объектам не так просто.