Je souhaite développer une application C ++ multithread (où la plupart des codes C ++ seraient générés par l’application elle-même, qui pourrait être considérée comme un langage spécifique à un domaine de haut niveau) sous Linux / AMD64 / Debian avec GCC 4.6 (et probablement la dernière norme C ++ 11).
Je veux vraiment utiliser le ramasse-miettes conservateur de Boehm pour toutes mes allocations de tas, car je veux allouer avec new(GC)
et ne jamais me soucier de la delete
. Je suppose que le GC de Boehm fonctionne assez bien.
La principale motivation pour utiliser C ++ (au lieu de C) réside dans tous les algorithmes et collections std::map
… std::vector
fournis par la bibliothèque standard C ++.
Le GC de Boehm fournit un gc_allocator
template (dans son fichier gc / gc_allocator.h).
Dois-je redéfinir operator ::new
comme celui de Boehm?
Ou dois-je utiliser tous les modèles de collection avec un argument de modèle d’allocation explicite défini sur un gc_allocator
? Je ne comprends pas exactement le rôle de l’argument du second modèle (l’allocateur) dans std :: vector ? Est-il utilisé pour allouer les données internes vectorielles ou pour allouer chaque élément individuel?
Et que dire de std::ssortingng
-s? Comment atsortingbuer leurs données au GC? Dois-je avoir ma propre chaîne, en utilisant le template basic_ssortingng
avec gc_allocator
? Existe-t-il un moyen d’obtenir le tableau interne de char alloué avec GC_malloc_atomic
non GC_malloc
?
Ou conseillez-vous de ne pas utiliser Boehm GC avec une application compilée par g ++?
Cordialement.
Pour répondre en partie à ma propre question, le code suivant
// file myvec.cc #include #include #include #include class Myvec { std::vector > _vec; public: Myvec(size_t sz=0) : _vec(sz) {}; Myvec(const Myvec& v) : _vec(v._vec) {}; const Myvec& operator=(const Myvec &rhs) { if (this != &rhs) _vec = rhs._vec; return *this; }; void resize (size_t sz=0) { _vec.resize(sz); }; int& operator [] (size_t ix) { return _vec[ix];}; const int& operator [] (size_t ix) const { return _vec[ix]; }; ~Myvec () {}; }; extern "C" Myvec* myvec_make(size_t sz=0) { return new(GC) Myvec(sz); } extern "C" void myvec_resize(Myvec*vec, size_t sz) { vec->resize(sz); } extern "C" int myvec_get(Myvec*vec, size_t ix) { return (*vec)[ix]; } extern "C" void myvec_put(Myvec*vec, size_t ix, int v) { (*vec)[ix] = v; }
lorsqu’il est compilé avec g++ -O3 -Wall -c myvec.cc
produit un fichier object avec
% nm -C myvec.o U GC_free U GC_malloc U GC_malloc_atomic U _Unwind_Resume 0000000000000000 W std::vector >::_M_fill_insert(__gnu_cxx::__normal_iterator > >, unsigned long, int const&) U std::__throw_length_error(char const*) U __gxx_personality_v0 U memmove 00000000000000b0 T myvec_get 0000000000000000 T myvec_make 00000000000000c0 T myvec_put 00000000000000d0 T myvec_resize
Il n’y a donc pas de simple malloc ou ::operator new
dans le code généré.
Donc, en utilisant gc_allocator
et new(GC)
je peux être sûr que plain ::opertor new
ou malloc
n’est pas utilisé à mon insu, et je n’ai pas besoin de redéfinir ::operator new
Pour référence ultérieure (merci à Sergey Zubkov de l’avoir mentionné sur Quora dans un commentaire), voir aussi n2670 et
et le support de la récupération de la
(comme std :: declare_reachable , std :: declare_no_pointers , std :: pointer_safety etc …) . Cependant, cela n’a pas été implémenté (sauf dans la manière sortingviale mais acceptable de le transformer en un non-op) au moins dans le GCC ou le Clang actuel.