std::unique_ptr作为函数返回值导致的野指针

最近在使用unique_ptr时碰到一个奇怪的问题,先看一下如下这段代码

class T
{
public:
    ....
    int* getPayLoad() {return (int *)serial_payload.data();}
private:
    std::unique_ptr> serial_payload;
};

std::unque_ptr<> read()
{
  char msg[5] = {1, 2, 3, 4, 5};
  auto data = std::make_unique(msg, msg+5);
  return std::move(data);
}

int main()
{
  int * data = read()->getPayLoad();
  printf("data[0] = %d", data[0]);
}

其实代码比较简单

  • read函数创建了一个T的对象,T里面构造的时候创建了一个vector用来保存数据,同时私有的成员变量serial_payload保存了指向这个vector的指针;
  • 然后main函数中调用的时候,首先通过read函数读取了这个T对象的指针,然后调用T对象的getPayLoad函数来获取vector的数据指针
  • 然后打印这些数据
    看起来很简单,然而打印出来的时候取完全不是我们想要的结果,再把main中获取的data的地址打印出来,又和T类对象中创建vector的时候地址是一样的,这是怎么回事儿呢?
  • read()调用完成后,返回了一个unique_ptr指针,指向T类的对象,这个时候相当于这个对象的所有权转移到了main函数中;
  • 之后调用getPayLoad获取了T里面生成的vector对象指针保存到了data中
  • 这句话结束后,T对象这个时候并没有一个指针拥有它的所有权了,所以内存回收机制会把这段内存给回收了,也就是T对象里面创建的vector也被回收了,因为这个时候vecotr所在的内存块也没有指针拥有所有权了。
    所以实际上data这个时候是一个野指针。
    最快的修改方法可以如下这样
int main()
{
  auto data = read();
  int* data_payload = data->getPayLoad();

}

这样data就是一个unique_ptr指针,生命周期直到main函数的调用结束为止,这个过程中read中创建的对象不会被释放。

这里也涉及编码风格的问题,后面会考虑怎样的编码规范可以避免出现这种情况!这种问题通常出了就比较难查

你可能感兴趣的:(std::unique_ptr作为函数返回值导致的野指针)