C++ 替换默认STL分配器
我有一个大型(>250个文件)库的源代码,该库大量使用STL容器和字符串。我需要在具有有限堆的嵌入式环境中运行它,因此我希望确保该库本身的堆使用受到限制 显而易见的解决方案是创建一个分配器,但是修改整个代码库以包含分配器模板参数是最后的一个大任务,如果我想要获取源代码的新版本,这是不可取的。全局替换new和delete是不可行的,因为这会影响整个图像,而不仅仅是此库 我的下一个想法是一个愚蠢的C宏技巧,但这似乎是不可能的,尽管我承认自己不是一个聪明的宏作者 所以我想“是否有编译器或pragma开关在编译时指定分配器类”?但我什么都愿意 我要问的下一个问题是,如果有人能想出一个解决方案,那就是如何在组成这个库的一组文件中对new/delete执行同样的操作 我正在使用gcc 3.4.4工具链在Cygwin下运行它,目标是VxWorks,如果这能激发任何想法的话 所以我想“有没有编译器或pragma开关来指定 编译时的分配器类“?但我什么都愿意 不,没有 看一看 分配器是每个stl容器中的模板参数。你需要改变它们。在过去的嵌入式系统工作中,我也做过同样的事情。如果你愿意,我可以给你一些建议: 基本模板分配器:C++ 替换默认STL分配器,c++,stl,C++,Stl,我有一个大型(>250个文件)库的源代码,该库大量使用STL容器和字符串。我需要在具有有限堆的嵌入式环境中运行它,因此我希望确保该库本身的堆使用受到限制 显而易见的解决方案是创建一个分配器,但是修改整个代码库以包含分配器模板参数是最后的一个大任务,如果我想要获取源代码的新版本,这是不可取的。全局替换new和delete是不可行的,因为这会影响整个图像,而不仅仅是此库 我的下一个想法是一个愚蠢的C宏技巧,但这似乎是不可能的,尽管我承认自己不是一个聪明的宏作者 所以我想“是否有编译器或pragma开
namespace PFM_MEM {
template <class T>
class CTestInstAllocator {
public:
// type definitions
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
// rebind CTestInstAllocator to type U
template <class U>
struct rebind {
typedef CTestInstAllocator<U> other;
};
// return address of values
pointer address (reference value) const {
return &value;
}
const_pointer address (const_reference value) const {
return &value;
}
/* constructors and destructor
* - nothing to do because the CTestInstAllocator has no state
*/
CTestInstAllocator() {
}
CTestInstAllocator(const CTestInstAllocator&) {
}
template <class U>
CTestInstAllocator (const CTestInstAllocator<U>&) {
}
~CTestInstAllocator() {
}
// return maximum number of elements that can be allocated
size_type max_size () const {
return std::numeric_limits<size_t>::max() / sizeof(T);
}
// pvAllocate but don't initialize num elements of type T by using our own memory manager
pointer allocate (size_type num) {
/**
* pvAllocate memory custom memory allocation scheme
*/
return(pointer)(CPfmTestInstMemManager::pvAllocate(num*sizeof(T)));
}
// initialize elements of allocated storage p with value value
void construct (pointer p, const T& value) {
// initialize memory with placement new
new((void*)p)T(value);
}
// destroy elements of initialized storage p
void destroy (pointer p) {
// destroy objects by calling their destructor
p->~T();
}
// vDeallocate storage p of deleted elements
void deallocate (pointer p, size_type num) {
/**
*Deallocate memory with custom memory deallocation scheme
*/
CPfmTestInstMemManager::vDeallocate((void*)p);
}
};
// return that all specializations of this CTestInstAllocator are interchangeable
template <class T1, class T2>
bool operator== (const CTestInstAllocator<T1>&,
const CTestInstAllocator<T2>&) {
return true;
}
template <class T1, class T2>
bool operator!= (const CTestInstAllocator<T1>&,
const CTestInstAllocator<T2>&) {
return false;
}
}
在这里,您可以调用您的新建并删除堆上的工作
我可以为您提供一个如何构建一些基本内存管理器的示例,以进一步帮助您。您可以从使用EASTL(Enterprise Arts STL(部分)实现)中获益 这是为嵌入式/游戏开发而设计的,在这样的环境中 EASTL的分配器模型受著名出版物()中的思想启发(或类似?) EASTL非常适合自定义分配器事实上,它不附带分配器,因此需要提供一个(最小的)分配器才能让应用程序链接
下面是针对EASTL的github repo:我求助于预处理器以获得可能的解决方案,尽管它目前依赖于GCC 3.4.4实现 GCC
实现包括文件
,该文件又包括另一个文件
,该文件定义了一个宏,该宏定义了实现默认分配器基类的类
由于是在平台相关路径中找到的(/lib/gcc/i686 pc cygwin/3.4.4/include/c++/i686 pc cygwin/bits
),用我自己的“平台相关”实现取代它,我并不觉得(非常)脏
因此,我只需在源代码的include路径的根目录中创建一个文件夹bits/
,然后在该文件夹中创建文件c++分配器.h
。我将所需的宏定义为我的分配器类的名称,它就像一个符咒,因为gcc在搜索系统包含之前搜索我的包含路径
谢谢你的回复。我想我可以使用这个“解决方案”,它可能只在我使用3.4.4时才起作用。gcc 3.4.4已经足够旧了,可以贴上“完全损坏”的标签。为什么不切换到新版本?我认为在GCC中,这只是interna中的一个简单宏,您应该能够切换。默认设置为“新分配器”,但GCC提供了几种替代方案,如“malloc分配器”和池分配器等。假设您可以创建一个有限堆,然后仅为该库重载
operator new
,因此库中的所有operator new
调用都进入您的有限堆。当有限堆已满并且调用重载的运算符new
时,您希望采取什么行为?在这种情况下,您真的希望新的操作员失败吗?我不相信您会这样做,除非当operator new
出现故障时,该库仍然可以运行。如果库是数据库缓存,或者类似的东西。这个库是做什么的?我们的做法是创建一个模板类来包装我们使用的每个容器。请看我发布的一个问题:。它为你省去了一些麻烦,也使你更难犯错误。我对我们的解决方案并不完全满意,所以如果有人用更好的解决方案回答你的问题,我可能会考虑修改我们的解决方案。@ SeHe,3.4.4的原因是我们的目标系统是运行VxWorks的卫星硬件,并且该工具链仍然在3.4.4。我不知道“为什么”,只知道要求。所以你是说没有办法告诉STL全局使用自定义分配器;必须确保在使用stl类型时,使用自定义分配器定义它。“是吗?”奥伦斯说。对于特定的编译器,可能有一个选择,但我是根据我的经验单独谈论的。我和OP在同一个地方,不得不这么做。编辑更正的答案。@FailedDev,我在这里发布之前看到了那个页面,对此充满希望。如果我能想出如何使我的任意分配器成为一个“扩展”分配器,那我就太棒了。我也不知道该怎么做。如果你知道,我会给我的下一个狗命名“FieldDeV”……这个话题和C++ 17有什么变化吗?现在是否有一种通用的方法来替换全局分配器?这是一种可能的解决方案,尽管由于std和EASTL名称空间的关系,我不得不编辑EASTL或我的库。我如何在Visual Studio中这样做?我试图找到默认的分配器头文件,但丢失了:)谢谢!
/**
* pvAllocate memory custom memory allocation scheme
*/
return(pointer)(CPfmTestInstMemManager::pvAllocate(num*sizeof(T)));
// vDeallocate storage p of deleted elements
void deallocate (pointer p, size_type num) {
/**
*Deallocate memory with custom memory deallocation scheme
*/
CPfmTestInstMemManager::vDeallocate((void*)p);