Remplacer l’allocateur STL par défaut

J’ai le code source d’une grande bibliothèque (> 250 fichiers) qui utilise beaucoup les conteneurs et les chaînes STL. Je dois l’exécuter dans un environnement embarqué avec un tas limité. Je veux donc m’assurer que cette bibliothèque elle-même est limitée dans son utilisation de tas.

La solution évidente est de créer un allocateur, mais la modification de la base de code complète pour inclure le paramètre de modèle d’allocateur est un gros travail de dernier recours, et indésirable au cas où je voudrais utiliser une nouvelle version de la source. Remplacer globalement new et delete n’est pas faisable car cela affecte l’ensemble de l’image, pas seulement cette bibliothèque.

Ma pensée suivante était une astuce macro C stupide, mais cela ne semble pas possible, bien que j’avoue ne pas être un auteur de macro intelligent.

Alors je me suis dit “existe-t-il un compilateur ou un commutateur pragma pour spécifier la classe allocateur au moment de la compilation”? Mais je suis ouvert à tout.

La prochaine question que je poserai, si quelqu’un peut trouver une solution, est de savoir comment faire de même pour new / delete dans l’ensemble des fichiers composant cette bibliothèque.

J’utilise la chaîne d’outils gcc 3.4.4 pour l’exécuter sous Cygwin, avec une cible de VxWorks, si cela suscite des idées.

J’ai eu recours au préprocesseur pour trouver une solution, bien qu’il repose actuellement sur la mise en œuvre de GCC 3.4.4.

L’implémentation GCC inclut le fichier , qui inclut à son tour un autre fichier , qui définit une macro qui définit la classe implémentant la classe de base allocateur par défaut.

Puisque se trouve dans un chemin dépendant de la plate-forme ( /lib/gcc/i686-pc-cygwin/3.4.4/include/c++/i686-pc-cygwin/bits ) , je ne me sens pas (très) sale de le supplanter. avec ma propre implémentation “dépendante de la plate-forme”.

Je crée donc un dossier bits/ à la racine du chemin d’inclusion de ma source, puis crée le fichier c++allocator.h dans ce dossier. Je définis la macro requirejse comme étant le nom de ma classe d’allocateur et fonctionne comme un charme, car gcc recherche dans mes chemins d’inclusion avant de rechercher dans le système inclus.

Merci pour toutes vos réponses. Je pense que je peux aller avec cette “solution”, qui ne fonctionnera que tant que j’utilise 3.4.4 probablement.

Vous pourriez bénéficier de l’implémentation EASTL (Enterprise Arts STL (partielle))

EASTL – Bibliothèque de modèles standard Electronic Arts

Cela était destiné au développement de jeux / embarqués, dans des environnements où le tas global est vraiment rare, inexistant ou problématique en général .

Le modèle allocateur de EASTL a été inspiré (ou ressemble ?) Aux idées de la célèbre publication Vers un meilleur modèle d’allocateur ( PDF ).

L’EASTL se prête bien aux allocateurs personnalisés. En fait, il n’est pas livré avec un allocateur , vous devez donc en fournir un (minime) pour que votre application puisse même être liée.

Voici le repo de github pour EASTL: https://github.com/paulhodge/EASTL

Alors je me suis dit “existe-t-il un compilateur ou un commutateur pragma pour spécifier la classe allocateur <> au moment de la compilation”? Mais je suis ouvert à tout.

Non il n’y en a pas.

Jetez un coup d’oeil ici .

Les allocateurs sont un argument de modèle dans chaque conteneur stl. Vous devrez les changer. J’ai fait la même chose dans le passé, lorsque je travaillais sur Embedded. Je pourrais vous donner quelques indications si vous aimez:

Allocateur de modèle de base:

 namespace PFM_MEM { template  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  struct rebind { typedef CTestInstAllocator 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  CTestInstAllocator (const CTestInstAllocator&) { } ~CTestInstAllocator() { } // return maximum number of elements that can be allocated size_type max_size () const { return std::numeric_limits::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  bool operator== (const CTestInstAllocator&, const CTestInstAllocator&) { return true; } template  bool operator!= (const CTestInstAllocator&, const CTestInstAllocator&) { return false; } } 

Prenez particulièrement note à ces lignes:

 /** * 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); 

Voici l’endroit où vous appelez votre nouveau et supprimez ce qui fonctionne sur votre tas.

Je pourrais vous donner un exemple sur la façon de construire un gestionnaire de mémoire de base pour vous aider davantage.