Segfault в C ++, вызывающий виртуальный метод для объекта, созданного в предварительно выделенном буфере - PullRequest
0 голосов
/ 05 октября 2010

Хм ... Заголовок немного глоток, но я действительно не уверен, какая часть этого вызывает проблемы, я пробежался по нему множество раз и не могу точно определить, почему ...

Идея состоит в том, чтобы один экземпляр Choice мог хранить любое значение любого из типов, переданных в его список шаблонов ... Это похоже на объединение, за исключением того, что он отслеживает типхранится и рассматривает значения каждого типа как отдельные, что позволяет обойти ограничения C ++ для конструкторов в членах объединения.

В некоторых случаях это работает, но, похоже, возникают некоторые проблемы скод очисткиЯ начал получать segfaults, как только начал использовать эту структуру с std :: basic_string или аналогичными типами, переданными в списке аргументов, но я не понимаю, почему это может вызвать проблемы.

Это вроде какЭксперимент для себя, но я не вижу никакой причины, почему это не должно работать (скомпилировано в режиме C ++ 0x в g ++):

// virtual methods should provide a way of "remembering"
// the type stored within the choice at any given time
struct ChoiceValue
{
   virtual void del(void* value) = 0;
   virtual bool is(int choice) = 0;
};

// Choices are initialized with an instance
// of this structure in their choice buffer
// which should handle the uninitialized case
struct DefaultChoiceValue : public IChoiceValue
{
   virtual void del(void* value) {}
   virtual bool is(int choice) { return false; }
};

// When a choice is actually initialized with a value
// an instance of this structure (with the appropriate value
// for T and TChoice) is created and stored in the choice
// buffer, allowing it to be cleaned up later (using del())
template<int TChoice, typename T>
struct ChoiceValue
{
    virtual void del(void* value) { ((T*)value)->~T(); }
    virtual bool is(int choice) { return choice == TChoice; }
};

template<typename ... TAll>
struct Choice
{
};

template<typename T1, typename ... TRest>
struct Choice<T1, TRest...>
{
  // these two constants should compute the buffer size needed to store
  // the largest possible value for the choice and the actual value
  static const int CSize = sizeof(ChoiceValue<0, T1>) > Choice<TRest...>::CSize
         ? sizeof(ChoiceValue<0, T1>) : Choice<TRest...>::CSize;
  static const int VSize = sizeof(T1) > Choice<TRest...>::VSize
         ? sizeof(T1) : Choice<TRest...>::VSize;

   IChoiceValue* _choice;
   char* _choiceBuffer;
   char* _valueBuffer;

   Choice()
   {
      _choiceBuffer = new char[CSize];
      _valueBuffer = new char[VSize];
      _choice = new (_choiceBuffer) DefaultChoiceValue();
   }
   ~Choice()
   {
      _choice->del(_valueBuffer);
      delete[] _choiceBuffer;
      delete[] _valueBuffer;
   }
   template<int TChoice, typename T>
   T& get()
   {
      if(_choice->is(TChoice))
        return *(T*)_valueBuffer;
      else
      {
         _choice->del(_valueBuffer);
         new (_valueBuffer) T();
         _choice = new (_choiceBuffer) ChoiceValue<TChoice, T>();
         return *(T*)_valueBuffer;
      }
   }
};

template<typename T1>
struct Choice<T1>
{
  // required for the base case of a template
  // with one type argument
  static const int CSize = sizeof(ChoiceValue<0, T1>) > sizeof(DefaultChoiceValue)
              ? sizeof(ChoiceValue<0, T1>) : sizeof(DefaultChoiceValue);
  static const int VSize = sizeof(T1);

  // I have an implementation here as well in my code
  // but it is pretty much just a copy of the above code
  // used in the multiple types case
};

Спасибо большое, если кто-нибудь сможет узнать, что я 'я делаю неправильно:)

1 Ответ

4 голосов
/ 05 октября 2010

Вы не опубликовали никакого кода, связанного с фактическим сбоем, но я собираюсь предположить, что вы либо возвращаете экземпляр Choice<...> по значению, либо вызываете конструктор копирования другими способами.Поскольку вы не определили конструктор копирования, вы, вероятно, дважды освобождаете память, выделенную для Choice<...>::Choice.

...