向量故障中的shared_ptr-迭代和丢失范围-获取损坏的数据
shared_ptr in vector trouble - iterating and losing scope - getting corrupted data
我对C++并不陌生,但我通常主要使用C#和其他托管语言,所以我不太熟悉共享指针等。
我基本上有一个共享ptrs到自定义类对象的三维映射(用于三维目的)。
这些shared_ptr位于地图中,并在整个项目中被引用,到目前为止效果良好。对于一个特定的功能,我将其中一些shared_ptr存储在一个向量中,以便稍后在代码中迭代,但这似乎是事情崩溃的地方。
假设我有100个这样的对象,它们的指针存储在三维地图中,其中3个被添加到向量中,因为它们具有特殊的功能属性。当我遍历向量时,我会调用这3个对象上的函数。这一切都很好,直到for循环(用于迭代)在向量的元素[1]上第二次运行,此时元素[0]充满了损坏的数据(但元素[1]需要访问元素[0]才能执行其中一个函数),这就是我得到错误的地方。
正如我所说,我不太熟悉shared_ptrs,但我认为数据不会被破坏,因为实际对象是在创建三维地图的过程中创建的——而且,矢量还没有超出范围,因为我只在第二次运行for循环(有3个对象,因此有3次迭代)。
我知道我一定做错了什么,但我不知道如何进一步调试它——基本上,当我遍历代码并进入for循环的第二次运行时,如果我在向量中查看元素[0]的shared_ptr(使用VS),它都已损坏。
这是代码的循环,所以您可以看到。向量是在该代码所在的类的构造函数中创建的,映射(其中创建了shared_ptrs和对象)在应用程序的主类中。此外,getAdjacent将objA和objB作为指针,因此用objA:的相邻对象的数据"填充"objB
for(vector<shared_ptr<ObjectClass>>::iterator iterator = objects.begin(); iterator != objects.end(); iterator++)
{
shared_ptr<ObjectClass> objA = (shared_ptr<ObjectClass>) iterator->get();
shared_ptr<ObjectClass> objB;
m_3DMap->getAdjacent(objA, objB);
objA->move(objB);
}
这可能与我在iterator->get()
上表演的演员阵容有关吗?我看不到任何其他方法可以做到这一点,因为如果我没有强制转换,VS说它不能从ObjectClass*转换为shared_ptr,这对我来说也很困惑,因为我认为我有一个shared_ptrs的向量?。。
谢谢你抽出时间,如果有人能帮忙就太好了。
对于初学者来说,应该很少在shared_ptr上调用get()。并且使用该指针初始化另一个shared_ptr,你永远不能这样做。
从中构造智能指针的原始指针将被传递以获得所有权。所有权必须是排他性的。使用它的方式是,两个shared_ptr将拥有同一个对象,导致过早删除,然后在某个时候进行双重删除,这两个都会让你进入UB。
这比原来的要好一些,但在没有看到代码的情况下,getAdjacent也有可能以某种方式被破坏。
for(auto i = objects.begin(); i != objects.end(); ++i)
{
const auto& objA = *i;
shared_ptr<ObjectClass> objB;
m_3DMap->getAdjacent(objA, objB);
objA->move(objB);
}
getAdjacent的签名应该类似于
void getAdjacent(shared_ptr<ObjectClass> const& objA, shared_ptr<ObjectClass>& objB);
有战斗的机会。
好的,我发现了我的问题。
这在一定程度上与Balog-Pal所说的将shared_ptrs放在向量中有关,即使它们位于地图中,所以我改变了这一点,使向量包含指向shared_ptr的指针。尽管这可能仍然是一种糟糕的做法,但它解决了这个问题,尤其是当向量是局部的,并且在函数退出后失去了作用域时。
最初的向量方法是在我在函数中的某个位置对映射迭代器进行解引用时实现的,因此我决定将所有映射操作都放在迭代之外(因此将"特殊"对象存储在向量中,以便稍后迭代)。
我现在已经更改了实现以消除这种低效性,因为我的操作函数现在返回了一个新的映射迭代器,从而解决了这个问题。
如果错误消息更有帮助,那就太好了,因为我花了一些时间才意识到迭代器变得无效,因为我在"特殊"对象上调用的一个函数中隐藏了一个insert()。
虽然这个答案并没有真正回答我所问的确切问题,但它回答了整个问题,以及我为什么按照问题中的方式设计函数。
感谢巴洛格的帮助,感谢它的回答和评论。
- 在 gcc/clang (C++) 中获取函数范围之外的标签地址
- 解析模板和范围后获取编译文件?
- 如何获取特定范围内的地图lower_bound?
- 从(排序的)数字列表中获取数字范围
- QT图表:如何获取QAbstractAxis的范围?
- 在<Object>基于范围的 for 循环中从 std::vector 获取指向对象的指针
- 在某些范围更新后获取整数数组的最终状态的有效算法是什么?
- 获取变量的中间范围值
- 范围 V3:获取基本迭代器
- 如何在标题文件中获取成员功能的正确代码覆盖范围
- 直接获取基于范围的循环中的元素类型 **例如"using"
- 给定 N 个范围.有多少种方法可以从这些范围中获取 N 个数字,这些数字的总和达到某个值
- 获取提升程序选项以在函数范围之后保留
- 为什么基于范围的 for 语句通过 auto&& 获取范围?
- 如何获取当前的 Windows 系统范围的计时器分辨率
- 获取迭代器范围的每个第 n 个元素
- 按字典顺序从范围中获取下一个数字(不包含所有字符串的容器)
- 在基于范围的 for 循环中获取无效引用
- 向量故障中的shared_ptr-迭代和丢失范围-获取损坏的数据
- Cuda推力::device_vector从特定范围获取指针