Стандартная библиотека C ++ и сборщик мусора Boehm - PullRequest
6 голосов
/ 05 ноября 2011

Я хочу разработать многопоточное приложение C ++ (где в конечном итоге большая часть кода C ++ будет сгенерирована самим приложением, которое можно рассматривать как высокоуровневый язык, специфичный для предметной области) на Linux / AMD64 / Debian с GCC4.6 (и, вероятно, последний стандарт C ++ 11).

Я действительно хочу использовать Консервативный сборщик мусора Бома для всех моих распределений кучи, потому что я хочу выделить с помощью new(GC) и никогда не беспокоиться о delete.Я предполагаю, что GC Бема работает достаточно хорошо.

Основным мотивом использования C ++ (вместо C) являются все алгоритмы и коллекции std::map ... std::vector, предоставляемые стандартной библиотекой C ++.

ГК Boehm предоставляет шаблон gc_allocator<T> (в его файле gc / gc_allocator.h).

Должен ли я переопределить operator ::new как Boehm?

Или я должен использовать все шаблоны коллекций с явным аргументом шаблона распределителя, установленным в значение gc_allocator?Я не совсем понимаю роль второго аргумента шаблона (распределителя) для std :: vector ?Используется ли он для выделения внутренних данных вектора или для выделения каждого отдельного элемента?

А как насчет std::string -s?Как сделать их данные GC-выделенными?Должен ли я иметь свою собственную строку, используя шаблон basic_string с gc_allocator?Есть ли какой-нибудь способ получить внутренний массив символов char, выделенный с помощью GC_malloc_atomic, а не GC_malloc?

Или вы советуете не использовать Boehm GC с приложением, скомпилированным g ++?

С уважением.

1 Ответ

4 голосов
/ 05 ноября 2011

Чтобы частично ответить на мой собственный вопрос, следующий код

// file myvec.cc
#include <gc/gc.h>
#include <gc/gc_cpp.h>
#include <gc/gc_allocator.h>
#include <vector>

class Myvec {
  std::vector<int,gc_allocator<int> > _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; }

при компиляции с g++ -O3 -Wall -c myvec.cc создает объектный файл с

 % nm -C myvec.o
                 U GC_free
                 U GC_malloc
                 U GC_malloc_atomic
                 U _Unwind_Resume
0000000000000000 W std::vector<int, gc_allocator<int> >::_M_fill_insert(__gnu_cxx::__normal_iterator<int*, std::vector<int, gc_allocator<int> > >, 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

Так что нет простого malloc или ::operator new в сгенерированном коде.

Таким образом, используя gc_allocator и new(GC), я, очевидно, могу быть уверен, что обычный ::opertor new или malloc не используется без моего ведома, и мне не нужнопереопределить ::operator new


addenda (январь 2017 г.)

Для дальнейшего использования (спасибо Сергею Зубкову за упоминание об этом Quora в комментарии), см.также n2670 и <memory> и поддержка сбора мусора (например, std :: Declare_reachable , std :: Declare_no_pointers , std:: pointer_safety etc ...).Тем не менее, это не было реализовано (за исключением тривиального, но приемлемого способа сделать его неработоспособным) в текущем GCC или Clang по крайней мере.

...