使用std :: vector = -operation到未初始化空间的Segfault

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用std :: vector = -operation到未初始化空间的Segfault相关的知识,希望对你有一定的参考价值。

当我使用= -operator将包含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类型是一个带有std :: vector结构的结构。我怀疑std :: vector = -operator以某种方式使用左侧变量newBuffer[i]并且因为newBuffer[i]未初始化而发生分段错误。

只使用函数T & operator[](size_t index)的in-placement new创建对象。 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;
}

没有段错误,它工作正常。我认为这是因为未初始化的内存对于std :: vector = -operation来说恰好是好的。

所以

a)理论是正确的

如果是的话

b)如何解决这个问题而不使用默认构造函数(T())为我的T用作ComponentContainer的每个类

答案

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

取消注释修复它的行!

如果你不能默认构造,那么复制构造:

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

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


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

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

以上是关于使用std :: vector = -operation到未初始化空间的Segfault的主要内容,如果未能解决你的问题,请参考以下文章

使用 std::vector 和内存释放

错误使用 std::vector<std::string> myString

包装 std::vector 的 std::vectors,C++ SWIG Python

将使用 PIMPL 习语的类存储在 std::vector 中

std::dynarray 与 std::vector

C++:使用 OpenMP 插入 std::vector