【问题标题】:How to split one heap into several heaps inside one process?如何在一个进程中将一个堆拆分为多个堆?
【发布时间】:2017-12-15 22:55:06
【问题描述】:

现在哪些生态系统允许创建多个堆?

AppDomain 不会创建新堆(所有域仍然有一个堆)。那么,在单个进程中启动多个不同的 GC 需要做什么?

需要创建哪些句法原语?运行时应该如何支持这些原语?

【问题讨论】:

    标签: memory-management garbage-collection language-agnostic heap-memory


    【解决方案1】:

    现在哪些生态系统允许创建多个堆?

    一个明显的答案是“C++”(如果您不认为一种语言本身是一个“生态系统”,请随意填写周围的部分)。

    C++ 允许您沿几个不同的轴指定堆。一种是按对象的类型——你可以通过重载operator newoperator delete 来为特定类型指定分配:

    class Foo { 
        static void *operator new(size_t size);
        static void operator delete(void *block, size_t size);
    };
    

    然后由您将这些堆管理功能连接到实际的内存源。您可以通过::operator new 分配它,或者您可以(例如)直接进入操作系统,例如在Windows 上使用GlobalAllocVirtualAlloc,在类UNIX 系统上使用sbrk,或者只使用pre - 裸机嵌入式系统上的指定内存块。

    沿着稍微不同的轴,C++ 标准库中的所有容器都通过分配器类分配和释放内存。任何特定集合的分配器都被指定为模板参数,因此(例如)std::vector 的声明看起来像这样:

    template <class T, class Alloc=std::allocator<T>>
    class vector {
        // ...
    };
    

    这使您可以指定一个堆,用于在该集合中分配对象。就像operator newoperator delete 一样,这实际上只指定了集合将分配和释放内存的接口——由您将其连接到实际管理堆的代码。

    垃圾回收

    就垃圾收集而言:我个人觉得它很烦人,并建议不要将其用作一般规则。问题是它虽然可以(至少从一个角度)解决某些类型的内存管理问题,但它对其他资源的管理没有任何帮助——而且(不幸的是)我还没有看到像跟踪收集器这样的东西文件句柄、网络套接字、数据库连接等等。 RAII 提供了一个统一的方法来处理一般的资源管理。

    也就是说,如果你真的坚持使用 GC,C++ 也确实支持。在 C++11 之前,GC 在实际层面上完全可用,但在一些晦涩的情况下会导致技术上未定义的行为,例如:

    • 将指针存储在文件中,然后将其读回,或者
    • 修改指针的位,然后撤消该修改

    ...然后获取重新构成的指针并取消引用它。显然,虽然指针对 CPU 不可见,但指向的内存块变得符合 GC 条件,因此后来的取消引用引起了问题。 C++11 定义了这些情况,并添加了一些库调用(例如,declare_reachableundeclare_reachable)来处理它们(例如,如果您调用decalare_reachable(block);,那么block 不符合收集条件,无论如何指向它的指针是否可见)。因此,如果您想将 GC 与 C++ 一起使用,您可以,并且已彻底指定定义行为的界限。唯一的问题是,基本上没有代码调用过declare_reachable 和/或undeclare_reachable,因此在实际使用中它们可能几乎没有帮助(但指针调配和/或文件中的存储非常罕见,以至于这不太可能造成真正的问题)。

    对于一个实际示例,您可能需要查看Boehm-Demers-Weiser collector(如果您还没有的话)。

    【讨论】:

      猜你喜欢
      • 2020-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-09-28
      相关资源
      最近更新 更多