【问题标题】:New vs. Malloc, when overloading New重载 New 时,New 与 Malloc
【发布时间】:2011-11-19 12:52:14
【问题描述】:

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

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

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

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

(这主要是出于好奇,尽量不要太认真地看待过载背后的原因;我对此有一个单独的问题!)

【问题讨论】:

  • 听起来是个很难回答的问题,因为如果不直接调用newmalloc(),我想不出任何其他方式在C++ 中分配内存?我是不是误会了什么?
  • @Mysticial - 我不这么认为!我想我们都会尽快找出是否有办法。 :P
  • 当然我忘记了操作系统特定的内存分配器...... :)
  • new vs malloc 问题没有考虑“重载new”的情况。 malloc() 的最大问题 - 不调用 ctors - 在这里无关紧要。

标签: c++ memory-management malloc


【解决方案1】:

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

堆管理器,例如 Linux 的 glibc 中的 malloc,Windows 中的 HeapAlloc,是一种用户级算法。首先,请记住,堆针对分配小尺寸对象(例如 4~512 字节)进行了优化。

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

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

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

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

【讨论】:

  • 哦,太好了!当然,它依赖于操作系统,但我想这就是重载new 的代价。谢谢!
  • 在这种情况下,对操作系统的依赖是不可避免的,但这很简单。您只需对虚拟内存分配 API 进行抽象函数调用。一个简单的#ifdef 也可以(参见 dlmalloc 源代码)。
【解决方案2】:

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

【讨论】:

  • 这只是委托给全局new/delete,如果你甚至没有实现这两个函数,它会自动发生。我是否遗漏了一些使它有用的东西?
  • @wjl 是的,它只是委托给全局 new/delete,但由于他在问题中声明它是针对小对象线程安全分配器的,因此他可以更改示例(仅显示如何他可以分配内存)并实现缓存或他需要的任何东西。
猜你喜欢
  • 1970-01-01
  • 2016-03-23
  • 2023-03-11
  • 1970-01-01
  • 2015-10-11
  • 2021-04-09
  • 2010-10-22
  • 2021-08-22
相关资源
最近更新 更多