C++ C++;库允许自定义分配器吗?

C++ C++;库允许自定义分配器吗?,c++,memory-management,c++14,allocation,C++,Memory Management,C++14,Allocation,在C语言中,库允许用户使用全局函数指针自定义内存分配,全局函数指针指向的函数应类似于malloc(),指向的函数应类似于free()。例如,SQLite使用这种方法 由于分配和初始化通常是融合在一起的,所以C++使事情变得有点复杂。本质上,我们只想得到一个库重写操作符new和操作符delete的行为,但实际上没有办法做到这一点(我相当肯定,但不是100%) 这是如何在C++中实现的?< /P> 这是第一次尝试使用函数Lib::make复制new表达式的一些语义 我不知道这是否有用,但只是为了好玩

在C语言中,库允许用户使用全局函数指针自定义内存分配,全局函数指针指向的函数应类似于
malloc()
,指向的函数应类似于
free()
。例如,SQLite使用这种方法

由于分配和初始化通常是融合在一起的,所以C++使事情变得有点复杂。本质上,我们只想得到一个库重写
操作符new
操作符delete
的行为,但实际上没有办法做到这一点(我相当肯定,但不是100%)

<>这是如何在C++中实现的?< /P> 这是第一次尝试使用函数
Lib::make
复制
new
表达式的一些语义

我不知道这是否有用,但只是为了好玩,这是一个更复杂的版本,它还试图复制
new[]
表达式的语义

这是一个面向目标的问题,所以我不一定要查看代码。如果有更好的方法可以做到这一点,就说出来,忽略链接

(我所说的“分配器”只是指分配内存的东西。我指的不是STL分配器的概念,甚至不是为容器分配内存。)


为什么这可能是可取的:


这是一篇来自Mozilla开发人员的博客文章,认为图书馆应该这样做。他给出了几个C库的示例,这些库允许库用户自定义库的分配。我查看了其中一个示例SQLite的源代码,发现该特性也在内部用于通过故障注入进行测试。我并没有写任何需要像SQLite那样防弹的东西,但它似乎仍然是一个明智的想法。如果没有别的,它允许客户代码来确定“哪一个库占用了我的内存和何时?”< /P> < P>简单的答案:不要使用C++。对不起,开玩笑

<>但是如果你想对C++中的内存管理进行绝对控制,跨库/模块边界,并且以一种完全概括的方式,你可能会陷入一些可怕的悲伤。我建议大多数人寻找不做这件事的理由,而不仅仅是方法

多年来(实际上是几十年来),我已经多次重复这一基本思想,从试图在全球层面上天真地重载操作符new/new[]/delete/delete[],到基于链接器的解决方案,再到平台特定的解决方案,事实上,我正处于你们现在所期望的位置:我有一个系统,可以让我看到每个插件分配的内存量。但我并没有通过你想要的那种广义的方式达到这一点(最初我也是这样)

C++使事情变得有点复杂,因为分配和初始化都是复杂的 通常是熔合的

<>我会对这个声明略微歪曲:C++使事情变得复杂,因为初始化和分配通常是融合的。我所做的只是在这里交换顺序,但最复杂的部分不是分配想要初始化,而是因为初始化通常想要分配

就拿这个基本的例子来说:

struct Foo
{
    std::vector<Bar> stuff;
};
。。。当然,我们可以按照RAII来包装这些,实现异常安全,等等

除了现在,问题层出不穷。使用
std::vector
stuff
成员将希望使用
std::allocator
,现在我们需要解决第二个问题。我们可以使用自己的分配器使用
std::vector
的模板实例化,如果需要将运行时信息传递给分配器,可以覆盖Foo的构造函数,将该信息与分配器一起传递给vector构造函数

但是关于
呢?它的构造器可能还想为各种不同的对象分配内存,因此问题层出不穷

考虑到这个问题的难度,以及我尝试过的其他通用解决方案,以及移植时带来的痛苦,我决定采用一种完全非通用的、有些务实的方法

我解决的方法是有效地重新创建整个C和C++标准库。我知道这很恶心,但我有更多的理由这么做。我正在开发的产品实际上是一个引擎和软件开发工具包,旨在允许人们使用任何编译器、C运行时、C++标准库实现和他们希望的构建设置来编写插件。为了允许向量、集合或映射等内容以ABI兼容的方式通过这些中央API,除了许多C标准函数外,还需要滚动我们自己的标准兼容容器

然后,此devkit的整个实现围绕以下分配功能展开:

EP_API void* ep_malloc(int lib_id, int size);
EP_API void ep_free(int lib_id, void* mem);
。。。整个SDK围绕这两个方面展开,包括内存池和“子分配器”

对于我们无法控制的第三方库,我们只是SOL。这些库中的一些库在内存管理方面也有同样雄心勃勃的事情要做,试图覆盖这些事情只会导致各种冲突,打开各种各样的蠕虫罐头。在使用OGL之类的东西时,也有非常低级的驱动程序需要分配大量的系统内存,我们对此无能为力

然而,我发现这个解决方案很好地解决了一个基本问题:“谁/什么东西占用了所有的内存?”这个问题很快就得到了回答:这个问题通常比与时钟周期相关的类似问题更难回答(对此,我们可以启动任何分析器)。它只适用于我们控制下的代码,使用这个SDK,但是我们可以在每个模块的基础上使用这个系统得到非常彻底的内存分解。我们还可以设置内存使用的表面上限,以确保内存不足错误实际上得到了正确处理,而不实际尝试耗尽所有连续的pa
EP_API void* ep_malloc(int lib_id, int size);
EP_API void ep_free(int lib_id, void* mem);