现在哪些生态系统可以创建多个堆?
AppDomains不会创建新的堆(所有域都有一个堆)。那么,在单个流程中启动多个不同的GC需要做什么呢?
需要创建哪些语法原语?运行时应如何支持该原语?
答案 0 :(得分:0)
现在哪些生态系统可以创建多个堆?
一个明显的答案是“C ++”(如果你不认为语言本身就是一个“生态系统”,你可以随意填写你认为合适的周边文章。)
C ++允许您沿几个不同的轴指定堆。一种是通过对象的类型 - 您可以通过为该类型重载operator new
和operator delete
来指定特定类型的分配:
class Foo {
static void *operator new(size_t size);
static void operator delete(void *block, size_t size);
};
然后由您将这些堆管理功能连接到实际的内存源。您可以通过::operator new
分配,或者您可以(例如)直接转到操作系统,例如Windows上的GlobalAlloc
或VirtualAlloc
,UNIX上的sbrk
类似系统,或者只是在裸机嵌入式系统上预先指定了内存块。
沿着一个不同的轴,C ++标准库中的所有容器都通过Allocator类分配和释放内存。任何特定集合的Allocator都被指定为模板参数,因此(例如)std::vector
的声明如下所示:
template <class T, class Alloc=std::allocator<T>>
class vector {
// ...
};
这允许您指定将用于分配该集合中的对象的堆。与operator new
和operator delete
一样,这实际上只指定了集合将分配和释放内存的接口 - 由您将其连接到实际管理堆的代码。
就垃圾收集而言:我个人觉得它很烦人,并建议不要将其作为一般规则使用。问题是虽然它可以(至少从一个角度来看)修复内存管理的某些类型的问题,但它没有帮助管理其他资源 - 并且(不幸的是)我没有看到任何像跟踪收集器的东西文件句柄,网络套接字,数据库连接等。 RAII提供了一种统一的资源管理方法。
也就是说,如果你真的坚持使用GC,那么C ++也支持它。在C ++ 11之前,GC在实际层面上完全可用,但在一些不明确的情况下导致了技术上未定义的行为,例如:
...稍后重新构建指针并取消引用它。显然,虽然指针对CPU不可见,但是指向的内存块符合GC的条件,因此后来的解引用会导致问题。 C ++ 11定义了这些情况,并添加了一些库调用(例如,declare_reachable
,undeclare_reachable
)来处理它们(例如,如果你调用decalare_reachable(block);
,{{1}无论是否可以看到指向它的指针,它都不符合收集条件。因此,如果您想使用GC和C ++,则可以完全指定已定义行为的范围。唯一的问题是,基本上没有代码会调用block
和/或declare_reachable
,因此在实际使用中它们可能很少或没有帮助(但指针调整和/或存储在文件中是非常罕见的,这不太可能造成真正的问题。)
对于一个实际示例,您可能需要查看Boehm-Demers-Weiser collector(如果您还没有)。