我有一个大型(> 250个文件)库的源代码,它大量使用STL容器和字符串。我需要在具有有限堆的嵌入式环境中运行它,所以我想确保这个库本身在其堆使用方面受到限制。
显而易见的解决方案是创建一个分配器,但是修改整个代码库以包含allocator模板参数是最后的一项重要工作,如果我想要使用新版本的源,这是不可取的。全局替换new和delete是不可行的,因为这会影响整个图像,而不仅仅是这个库。
我的下一个想法是一个愚蠢的C宏技巧,但这似乎不太可能,虽然我承认不是一个聪明的宏作者。
所以我认为“在编译时是否有编译器或编译指示开关来指定分配器<>类”?但我对任何事都持开放态度。
我要问的下一个问题是,如果有人能提出解决方案,那么如何在包含该库的文件集中对新/删除做同样的事情。
我正在使用gcc 3.4.4工具链在Cygwin下运行它,目标是VxWorks,如果这引发了任何想法。
答案 0 :(得分:7)
我使用预处理器来获得可能的解决方案,尽管它目前依赖于GCC 3.4.4实现。
GCC <memory>
实现包含文件<bits/allocator.h>
,后者又包含另一个文件<bits/c++allocator.h>
,该文件定义了一个定义实现默认分配器基类的类的宏。
由于在依赖于平台的路径(/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/i686-pc-cygwin/bits
)中找到,因此我不会感到(非常)肮脏地用我自己的“平台相关”实现来取代它。 / p>
所以我只在源代码的包含路径的根目录中创建一个文件夹bits/
,然后在该文件夹中创建文件c++allocator.h
。我将所需的宏定义为我的分配器类的名称,它就像一个魅力,因为gcc在搜索系统包括之前搜索我的包含路径。
感谢您的所有回复。我想我可以使用这个“解决方案”,只有在我使用3.4.4时它才会起作用。
答案 1 :(得分:6)
您可以从使用EASTL(Enterprise Arts STL(部分)实施)
中受益EASTL -- Electronic Arts Standard Template Library
这适用于global heap is really scarce, non-existent or problematic in general的环境中的嵌入式/游戏开发。
EASTL的分配器模型的灵感来自(或类似于?)着名的Towards a Better Allocator Model出版物(PDF)中的想法。
EASTL非常适合自定义分配器。 实际上,它没有附带分配器 ,因此提供(最小的)必需甚至可以让应用程序链接。
以下是EASTL的github回购:https://github.com/paulhodge/EASTL
答案 2 :(得分:3)
所以我认为“是否有编译器或编译指示开关来指定 分配器&LT;&GT;在编译时上课“?但我对任何事情都持开放态度。
没有。
看看here。
分配器是每个stl容器中的模板参数。你需要改变它们。在使用嵌入式系统时,我在过去做过同样的事情。如果你愿意,我可以给你一些指示:
基本模板分配器:
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;
}
}
请注意以下几点:
/**
* 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);
在这里您可以调用您的 new并删除堆上的哪些工作。
我可以为您提供一个如何构建一些基本内存管理器的示例,以帮助您进一步。