代码之家  ›  专栏  ›  技术社区  ›  Darius Duesentrieb

segfault with std::vector=-对未初始化空间的操作

  •  -1
  • Darius Duesentrieb  · 技术社区  · 6 年前

    当我使用=-运算符将包含std::vector的结构复制到未初始化的内存时,会出现分段错误。 关键代码如下:

    template<typename T>
    ComponentContainer
    {
      T* buffer;
      size_t capacity;
      size_t m_size;
    
    public:
    
      ComponentContainer();
      ~ComponentContainer();
      size_t size();
      void resize(size_t size);
      T & operator[](size_t index);
    };
    
    template<typename T>
    void ComponentContainer<T>::resize(size_t newSize)
    {
      if(this->m_size >= newSize)
      {
        this->m_size = newSize;
      }
      else
      {
        if(this->capacity < newSize)
        {
          const size_t newCapacity = capacity*2;
          T* newBuffer = (T*)malloc(newCapacity*sizeof(T));
          for(size_t i = 0; i<m_size; i++)
          {
            // checks if this->buffer[i] is valid intialized memory
            if(pseudo_checkIfElementIsInitialized(i))
            {
              // when this is uncommented no segfault happens
              //new (&newBuffer[i]) T(); 
              newBuffer[i] = this->buffer[i]; // <- segfault happens here 
            }
          }
          this->capacity = newCapacity;
          free(this->buffer);
          this->buffer = newBuffer;
        }
        this->m_size = newSize;
      }
    }
    

    这个 T -当我得到segfault时,类型是一个结构的std::vector。 我怀疑std::vector=-运算符以某种方式使用了左侧变量 newBuffer[i] 分割错误发生在 新缓冲器[I] 未初始化。

    对象将仅与函数一起创建 T & operator[](size_t index) . malloc应该只分配内存而不初始化任何内容。

    我试着写一个简单的例子,但效果不太好:

    #include <iostream>
    #include <vector>
    
    
    struct Hello
    {
        Hello()
        {
            std::cout << "constructor" << std::endl;
        }
        ~Hello()
        {
            std::cout << "destructor" << std::endl;
        }
        std::vector<double> v = std::vector<double>(1);
    };
    
    
    int main()
    {
        Hello* buffer = (Hello*)malloc(1*sizeof(Hello));
        char* noise = (char*)buffer;
        for(size_t i = 0; i<sizeof(Hello); i++)
        {
            noise[i] = 100;
        }
        auto tmp = Hello();
        tmp.v[0] = 6.6;
        //new (&buffer[0]) Hello();
        buffer[0] = tmp;
        std::cout << buffer[0].v[0] << std::endl;
    
        return 0;
    }
    

    它在没有SegFault的情况下工作正常。我认为这是因为对于std::vector=-操作,未初始化的内存只是偶然的。

    所以

    a)这个理论正确吗?

    如果是

    b)如何在不使用默认构造函数的情况下解决这个问题( T() )对于我所用的每一个班级 T 为了我 ComponentContainer

    1 回复  |  直到 6 年前
        1
  •  1
  •   Lightness Races in Orbit    6 年前

    嗯,是的。无法分配给不存在的对象。

    取消对修复它的行的注释!

    如果不能默认构造,则复制构造:

    new (&newBuffer[i]) T(this->buffer[i]);
    

    如果你不能做到,那么,好吧,你知道其余的。


    malloc应该只分配内存而不初始化任何内容。

    你有没有可能低估了这句话的分量?您不只是获取内存,然后决定是否用一些值初始化它。在使用对象之前,必须实际创建对象;这不是可选的。您正在编程C++,而不是在磁带上操作位和字节: