【问题标题】:why does VS2013 throw an exception when destroying unique pointer?为什么VS2013在销毁唯一指针时会抛出异常?
【发布时间】:2015-01-12 07:27:57
【问题描述】:

您能否提供有关此异常的含义以及为什么仅在 unique_ptr 为 != nullptr 时才抛出该异常的见解?

代码编译并运行抛出异常。

唯一指针 pFace2 在被销毁时似乎抛出异常。
它在 == nullptr 时不会抛出异常。

VS2013 异常信息为:

Network.exe 中 0x00CA6A0C 处的第一次机会异常:0xC0000005: 访问冲突写入位置0xCCCCCCD0。

如果有这个异常的处理程序,程序可能是安全的 继续。

代码是:

 for (auto volume : domain) {
        std::cout << "Volume " << volume->getID() << "\n";
        for (auto face : volume->volumeFaces) {

      auto pNeighbourVolume = std::find_if(
          domain.begin(), domain.end(), [&](std::shared_ptr<controlVolume> i) {
            return i->getID() == face.getNeighbour();
          });

      if (pNeighbourVolume != domain.end()) {
        std::cout << "  connected to " << (*pNeighbourVolume)->getID() << "\n";

        //This pointer     
        std::unique_ptr<cvVolumeFace> pFace2 = (*pNeighbourVolume)->matchingFace(face); 

        std::cout << "\n";
      } //<- here is where code breaks
    }
    std::cout << "\n\n";
  }

匹配类型的定义是:

std::unique_ptr<cvVolumeFace> controlVolume::matchingFace(cvVolumeFace &neighboursFace) {
  for (auto face : volumeFaces) {
    if ((face.getNeighbour() == neighboursFace.getNeighbour()) &&
        (face.getArea() - neighboursFace.getArea() < face.matchTolerence())) {      
      std::cout << "Matched faces for " << face.getNeighbour() << " and " << neighboursFace.getNeighbour();
      std::unique_ptr<cvVolumeFace> pFace(&face);
      return pFace;
    }
  }
  std::cout << "ERROR: No matching face to return!\n";
  return nullptr;
};

中断发生在 memory.h 的第 116 行

void _Decref()
    {   // decrement use count
    if (_MT_DECR(_Mtx, _Uses) == 0)  //<-breaks here
        {   // destroy managed resource, decrement weak reference count
        _Destroy();
        _Decwref();
        }
    }

【问题讨论】:

  • 0xCCCCCCD0 是一个幻数。这意味着您正在使用未初始化的变量。
  • matchingFace()的返回类型是什么?除非对matchingFace(face) 的调用正在分配内存,否则您不应该使用std::unique_ptr。如果matchingFace只是从数据结构内部返回一个指针,那么您的代码正在循环并从其他数据结构内部删除对象。
  • 是的,返回一个像那种气味的唯一指针。看起来matchingFace应该返回一个cvVolume&,虽然我不知道RAII开放的cv类是怎样的。
  • 为什么返回 std::unique_ptr 是不好的做法?
  • 我们有一个赢家:std::unique_ptr&lt;cvVolumeFace&gt; pFace(&amp;face); return pFace;

标签: c++ c++11 visual-studio-2013 smart-pointers unique-ptr


【解决方案1】:

请记住,pFace2if (pNeighbourVolume != domain.end()) { ... } 块的末尾被销毁,因此它将尝试在那里删除其资源;在这种情况下,资源似乎是本地对象。

【讨论】:

  • 这有点像int x; delete &amp;x;——你正在删除一些没有用适当的新表达式动态分配的东西..强调不是动态分配的..
【解决方案2】:

智能指针不是在您的设计中不考虑对象生命周期的借口。 std::unique_ptr 是控制另一个对象拥有的对象或在有限范围内的对象的生命周期的一种非常好的方法。一般来说,这样的unique_ptr 不应该被传递 - 更好地保持所有权与该 unique_ptr 的所有者的生命周期并将原始指针传递给其他用户,他们永远不应该尝试获得所有权。另一方面,如果对象的各种访问器的生命周期不确定,那么也许应该考虑std::shared_ptr。这是一个更强大的抽象,完全支持弱引用等,但它也相当昂贵,因为它涉及单独分配的控制块和几个原子引用计数器。

【讨论】:

    猜你喜欢
    • 2015-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-25
    • 2011-10-19
    • 2021-04-28
    相关资源
    最近更新 更多