2011-11-23 108 views
18

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

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

我的下一个想法是愚蠢的C代码宏伎俩,但似乎并不像它会是可能的,虽然我承认我不是一个聪明的宏作者。

所以我想“有没有编译器或编译开关来指定分配<>在编译时类”?但我对任何事情都是开放的。

下一个问题我要问,如果有人能拿出一个解决方案,是怎么做的新的同/设定包括这个库文件中删除。

我用gcc 3.4.4工具链在Cygwin下运行它,用的VxWorks的目标,如果火花任何想法。

+0

gcc 3.4.4这已经足够老了,被标记为“完全破碎”。任何你不换用新版本的原因? – sehe

+0

我认为在GCC中,这只是一个简单的宏,在内部应该可以切换。默认是“新的分配器”,但GCC带有几个选择,比如“malloc分配器”和池分配器等等。 –

+0

假设你可以创建一个有限的堆,然后只为这个库重载'operator new',所以库中的所有'operator new'调用都会进入你有限的堆。当有限的堆满了并且调用了重载的'operator new'时,你想要什么样的行为?你真的想在这种情况下让'operator new'失败吗?我不相信你会这样,除非这个库在'operator new'失败时仍然可以运行。也许如果库是一个数据库缓存,或类似的东西。图书馆做什么? –

回答

6

我使出了预处理得到一个可能的解决方案,虽然它目前依赖于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中找到,所以我不觉得(非常)会用我自己的“依赖于平台”的实现取代它。

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

感谢您的回复。我想我可以使用这个“解决方案”,只要我使用3.4.4,这个解决方案就可以工作。

+0

关于如何在Visual Studio中执行此操作的任何想法?我试图找到默认的分配器头文件,但迷路了:)谢谢! – OSH

3

所以我想“编译时是否有编译器或编译指示开关指定 >分配器<>类?但我对任何事情都是开放的。

不,没有。

看看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); 

在这里你打电话新的地方并删除堆中的哪些工作。

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

+0

所以你说没有办法告诉STL全局使用自定义分配器;您必须确保在使用stl类型时使用自定义分配器来定义它。对? – OSH

+0

@OrenS。那么对于特定的编译器来说,可能有一种选择,但我只是从我的经验谈起。我和OP在同一个位置,必须这样做。编辑更正的答案。 – FailedDev

+0

@FailedDev,我在这里发布之前看过那个页面,并且很有希望。如果我能弄清楚如何让我的任意分配器成为一个'扩展'分配器,那我就是金。我也不知道该怎么做。如果你知道,我会给我的下一只狗命名为“FailedDev”... – Reilly

6

你可以受益于使用EASTL(企业艺术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

+0

这是一个可能的解决方案,但由于std vs eastl命名空间,我必须编辑EASTL或我的库。 – Reilly