New против Malloc, при перегрузке New - PullRequest
3 голосов
/ 18 сентября 2011

Я перегружаю new и delete для реализации моего собственного маленького объекта / потокобезопасного распределителя.

Проблема в том, что когда я перегружаю new, я не могу использовать new без нарушения универсальной причинности или хотя бы компилятора. В большинстве примеров, которые я нашел, где new перегружен, используйте Malloc() для фактического выделения. Но из того, что я понял в C ++, нет никакого варианта использования для Malloc().

Несколько ответов, похожих на этот, некоторые с меньшим количеством недовольных вне SO: В каких случаях я использую malloc против new?

Мой вопрос, как мне выделить фактическую память при перегрузке оператора new без использования Malloc()?

(Это из любопытства больше всего на свете, постарайтесь не воспринимать причины перегрузки слишком серьезно; у меня есть отдельный вопрос по этому поводу, во всяком случае!)

Ответы [ 2 ]

4 голосов
/ 18 сентября 2011

Краткий ответ: если вы не хотите существовать malloc, вам нужно внедрить свой собственный менеджер кучи .

Менеджер кучи, например malloc в glibc ofLinux, HeapAlloc в Windows, является алгоритмом пользовательского уровня.Во-первых, имейте в виду, что куча оптимизирована для размещения объектов небольшого размера, таких как 4 ~ 512 байт.

Как реализовать свой собственный менеджер кучи?По крайней мере, вы должны вызвать системный API, который выделяет кусок памяти в вашем процессе.Есть VirtualAlloc для Windows и sbrk для Linux.Эти API-интерфейсы выделяют большой кусок памяти, но размер должен быть кратным page size.Как правило, размер страницы в x86 и Windows / Linux составляет 4 КБ.

После получения части страницы вам необходимо реализовать свои собственные алгоритмы, позволяющие разделить эту большую память на меньшие запросы.Классическая (все еще очень практичная) реализация и алгоритм: dlmalloc: http://g.oswego.edu/dl/html/malloc.html

Для реализации необходимо иметь несколько структур данных для бухгалтерского учета и несколько политик для оптимизации.Например, для небольших объектов, таких как 16, 20, 36, 256 байт, менеджер кучи поддерживает список блоков каждого размера.Итак, есть список списков.Если запрашиваемый размер больше, чем размер страницы, он просто вызывает VirtualAlloc или sbrk.Однако эффективная реализация очень сложна.Вы должны учитывать не только скорость и затраты пространства, но также локальность и фрагментацию кэша.

Если вас интересуют диспетчеры кучи, оптимизированные для многопоточной среды, посмотрите tcmalloc: http://goog -perftools.sourceforge.net/doc/tcmalloc.html

3 голосов
/ 18 сентября 2011

Я не вижу проблем в вызове malloc () внутри новой перегрузки, просто убедитесь, что вы перегружаете delete, чтобы он вызывал free (). Но если вы действительно не хотите вызывать malloc (), один из способов - просто выделить достаточно памяти другим способом:

class A {
    public:
        /* ... */
        static void* operator new (size_t size) {
            return (void *)new unsigned char[size];
        }
        static void operator delete (void *p) {
            delete[]((unsigned char *)p);
        }
        /* ... */
};
...