使用std :: vector<>和std :: shared_ptr<>应该导致错误

时间:2015-06-08 22:50:32

标签: c++ c++11 g++ c++14

这是我正在做的事情的代码:

#include <iostream>
#include <vector>
#include <memory>
using namespace std;

int main()
{
  vector<int> ar = {1};

  shared_ptr<int> sp(&ar[0]);

  cout<<*sp<<endl; // ---- [1]

  ar[0] = 10;

  cout<<*sp<<endl; // ---- [2]

  ar.clear();

  cout<<*sp<<endl; // ---- [3]



  return 0;
}

输出将是:

1
10
10

而不是cout而不是[3]我认为,运行时应该有任何错误,因为要访问的对象已被删除。如何在10中打印[3]?或者我应该使用任何g++标志,我只是使用g++ -std=c++14 a1.cpp && ./a.out

编辑:在Coliru上运行后,我发现clang++正在提供

`*** glibc detected *** ./a.out: double free or corruption (fasttop):     0x0000000002138010 ***`

g++不是Coliru

3 个答案:

答案 0 :(得分:2)

当你试图在向量的当前边界之外访问时,你几乎绕过任何可以保证运行时错误的东西。

如果你想检查边界,你可能会考虑这样的事情:

std::vector<int> ar { 1 };

std::cout << ar.at(0); // no problem

ar.clear();

std::cout << ar.at(0); // guaranteed to throw an exception

shared_ptr用于共享对象的所有权,因此只有在没有任何东西拥有对象时才会删除该对象。相比之下,std::vector假定其所包含的所有对象的唯一所有权,因此尝试使用shared_ptr引用其中一个仅导致问题。

另一方面,如果gcc设法在没有问题的(可见)标志的情况下退出,那么在技术上并不符合编译器中的错误。在范围的最后,shared_ptrstd::vector都会尝试释放int引用的shared_ptr - 但不要求这样做会导致一个错误消息(官方认为这是一个执行质量问题,但我当然同意显示消息总比没有好。)

答案 1 :(得分:1)

这是一种未定义的行为。它可能会也可能不会打印10。

std::vector::clear()删除了对象并且无法保证重新分配。因此系统可能不会重用该内存,因此如果访问相同的内存位置,您可能会得到旧值。

有一个有趣的观察结果,如果您在std::shared_ptr::use_cout()操作后检查std::vector::clear(),则可以看到答案1.

  vector<int> ar = {1};

  shared_ptr<int> sp(&ar[0]);

  cout<<*sp<<"\n"; // ---- [1]

  ar[0] = 10;

  cout<<*sp<<"\n"; // ---- [2]

  ar.clear();
  cout<< sp.use_count()<<"\n";

  cout<<*sp<<endl; // ---- [3]

输出

1
10
1
10

答案 2 :(得分:1)

您的代码中存在一些错误。最明显的一点是,您正在创建shared_ptr来管理已由vector管理的对象,并且最有可能在main结束时进行双重删除。

另一个问题是你有一个指向对象的指针,并在对象被删除后使用它,因为std::vector<int>::clear没有释放你正在打击内存的内存由向量管理,这就是为什么它不会爆炸,但对象不再存在,你不应该访问它。如果它不是int而是std::string,程序可能已经崩溃(它可能也没有崩溃,这是未定义行为的本质)