当重载New时,New与Malloc



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

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

与此类似的多个答案,一些在SO之外的侵权行为较少:在什么情况下我使用malloc vs new?

我的问题是,当重载操作符new而不使用Malloc()时,我如何分配实际内存?

(这是出于好奇,尽量不要把过载背后的原因太当回事;我有一个单独的问题!)

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

堆管理器是一个用户级算法,例如Linux的glibc中的malloc, Windows的HeapAlloc。首先,请记住,堆是为分配小大小的对象(如4~512字节)而优化的。

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

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

要实现

,您需要有几个用于记账的数据结构和许多用于优化的策略。例如,对于像16,20,36,256字节这样的小对象,堆管理器维护每种大小的块列表。所以,有一个列表的列表。如果请求的大小大于页面大小,则只调用VirtualAllocsbrk。然而,高效的实现是非常具有挑战性的。您不仅要考虑速度和空间开销,还要考虑缓存位置和碎片。

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

我认为在一个新的重载中调用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);
        }
        /* ... */
};

相关内容

  • 没有找到相关文章

最新更新