新的与Malloc,重载新的

时间:2011-09-18 03:46:28

标签: c++ memory-management malloc

我正在重载newdelete以实现我自己的小对象/线程安全分配器。

问题在于,当我超载new时,我不能在不破坏普遍因果关系或至少编译器的情况下使用new。我发现大多数new重载的示例,请使用Malloc()进行实际分配。但根据我对C ++的理解,Malloc()根本就没有用例。

多个答案与此类似,有些在SO之外的侵权较少:In what cases do I use malloc vs new?

我的问题是,如何在不使用new的情况下重载运算符Malloc()时分配实际内存?

(这绝对是出于好奇,尽量不要太过认真地对待超载背后的推理;我对任何人都有一个单独的问题!)

2 个答案:

答案 0 :(得分:4)

简短回答:如果您不想要现有的malloc,则需要实现自己的堆管理器

堆管理器,例如Linux的glibc中的malloc,Windows中的HeapAlloc,是一种用户级算法。首先,请记住,堆已经过优化,可以分配4~512字节的小尺寸对象。

如何实现自己的堆管理器?至少,您必须调用在您的进程中分配内存块的系统API。 Windows为VirtualAlloc,Linux为sbrk。这些API分配了大量内存,但大小必须是 page 大小的倍数。通常,x86和Windows / Linux中的页面大小为4KB。

获取一大块页面后,您需要实现自己的算法,如何将这个大内存砍成更小的请求。经典(仍然非常实用)的实现和算法是dlmallochttp://g.oswego.edu/dl/html/malloc.html

要实施,您需要有多个用于记账的数据结构和一些用于优化的策略。例如,对于像16,20,36,256字节这样的小对象,堆管理器维护每个大小的块列表。所以,有一个列表列表。如果请求的尺寸大于页面尺寸,则只需拨打VirtualAllocsbrk即可。但是,有效的实施非常具有挑战性。您不仅要考虑速度和空间开销,还要考虑缓存局部性和碎片。

如果您对针对多线程环境优化的堆管理器感兴趣,请查看tcmallochttp://goog-perftools.sourceforge.net/doc/tcmalloc.html

答案 1 :(得分:3)

我在新的重载中调用malloc()没有问题,只是确保你重载删除所以它调用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);
        }
        /* ... */
};