替换默认的STL分配器

Replace default STL allocator

本文关键字:分配器 STL 默认 替换      更新时间:2023-10-16

我有一个大型(>250个文件(库的源代码,该库大量使用STL容器和字符串。我需要在具有有限堆的嵌入式环境中运行它,所以我想确保这个库本身的堆使用量受到限制。

显而易见的解决方案是创建一个分配器,但修改整个代码库以包含分配器模板参数是最后的一项艰巨任务,如果我想使用新版本的源代码,这是不可取的。全局替换new和delete是不可行的,因为这会影响整个图像,而不仅仅是这个库。

我的下一个想法是一个愚蠢的C宏技巧,但这似乎不可能,尽管我承认自己不是一个聪明的宏作者。

所以我想"是否有编译器或pragma开关在编译时指定分配器<>类"?但我对任何事情都持开放态度。

如果有人能想出解决方案,我将要问的下一个问题是,如何对构成该库的一组文件中的新文件/删除文件执行同样的操作。

我正在使用gcc 3.4.4工具链在Cygwin下运行它,目标是VxWorks,如果这能激发任何想法的话。

我求助于预处理器来获得一个可能的解决方案,尽管它目前依赖于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(中发现的,所以用我自己的"依赖于平台"实现来取代它并不觉得(非常(脏。

因此,我只需在源的include路径的根目录中创建一个文件夹bits/,然后在该文件夹中创建文件c++allocator.h。我将所需的宏定义为我的分配器类的名称,它就像一个魅力,因为gcc在搜索系统include之前搜索我的include路径。

感谢您的回复。我想我可以使用这个"解决方案",只要我可能使用3.4.4,它就会起作用。

您可以从使用EASTL(Enterprise Arts STL(部分(实现(中受益

EASTL——电子艺术标准模板库

这是为嵌入式/游戏开发而设计的,在这种环境中,全局堆非常稀缺、不存在或普遍存在问题。

EASTL的分配器模型的灵感来源于(或类似?(著名的《走向更好的分配器模型》出版物(PDF(中的想法。

EASTL非常适合自定义分配器事实上,它没有附带分配器,因此提供(最小(分配器是甚至让应用程序链接所必需的

以下是EASTL的github回购:https://github.com/electronicarts/EASTL

所以我想"是否有编译器或pragma开关来指定分配器<>类"?但我对任何事情都持开放态度。

没有

看看这里。

分配器是每个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并删除堆上的工作的地方。

我可以为您提供一个如何构建一些基本内存管理器的示例,以进一步帮助您。