c++ - C++ 中的段错误在预分配缓冲区中创建的对象上调用虚方法

标签 c++ templates gcc c++11 placement-new

嗯……标题有点啰嗦,但我真的不确定是哪一部分导致了问题,我已经经历了很多次,但无法确定原因……

这个想法是让单个 Choice 实例能够存储任何一个值 传递给它的模板列表的类型...有点像 union ,除了 它跟踪存储的类型,并认为每种类型的值是不同的,这允许它绕过 union 成员中构造函数的 C++ 约束。

它在某些情况下确实有效,但清理代码似乎存在一些问题。当我开始将此结构与参数列表中传递的 std::basic_string 或类似类型一起使用时,我开始出现段错误,但我不明白为什么这会导致任何问题。

这对我自己来说是一种虽然实验,但我看不出它为什么不起作用(在 g++ 中以 C++0x 模式编译):

// 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
};

非常感谢,如果有人能找出我做错了什么:)

最佳答案

您没有发布任何与实际崩溃相关的代码,但我猜您要么返回了一个 Choice<...> 的实例。通过值或通过其他方式调用复制构造函数。由于您没有定义复制构造函数,因此您可能会双重释放使用 Choice<...>::Choice 分配的内存。 .

关于c++ - C++ 中的段错误在预分配缓冲区中创建的对象上调用虚方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3859238/

相关文章:

c++ - 我试图访问 C++ 多态类的 vtable,但由于核心转储而失败,为什么?

c++ - C++中的大文件读取错误

c++ - 如何隐式专门化转换?

c++ - 具有模板的构造函数特化

c++ - 在尝试使用 SFINAE 禁用功能时,我是否创建了未定义的行为?

c - C 套接字读取函数造成内存泄漏

c++ - gcc 4.7.1 是否支持线程?

c++ - 计算一个非常大的矩阵的逆

c++ - clang 如何检测 noexcept-ness?

c++ - 在对象初始化中复制构造函数