添加到向量的 std::shared_ptr 会导致段错误
Adding to std::shared_ptr of vector causes segfault
我有这个示例程序。我想要做的就是在 vector 本身包含的对象之间共享一个 vector 实例,以便它们可以从容器中操作(添加其他对象,删除它们自己)。
#include <iostream>
#include <memory>
#include <vector>
class SimpleClass {
private:
std::shared_ptr<std::vector<SimpleClass>> objects;
public:
SimpleClass (std::shared_ptr<std::vector<SimpleClass>> _objects): objects { _objects } {}
void grow () {
std::cout << "growing" << std::endl;
for (int i { 0 }; i < 10; ++i) {
std::cout << "about to add a new object" << std::endl;
std::cout << "current simple_objects size: " << objects->size() << std::endl;
objects->push_back(SimpleClass(objects));
std::cout << "added a new object" << std::endl;
}
}
};
int main () {
auto simple_objects = std::make_shared<std::vector<SimpleClass>>();
for (int i { 0 }; i < 10; ++i) {
simple_objects->push_back(SimpleClass { simple_objects });
}
std::cout << "simple_objects size: " << simple_objects->size() << std::endl;
for (auto &obj: *simple_objects) {
obj.grow();
}
return 0;
}
经过一些迭代后,程序存在 Segmentation Fault 11
:
simple_objects size: 10
growing
about to add a new object
current simple_objects size: 10
added a new object
about to add a new object
current simple_objects size: 11
added a new object
about to add a new object
current simple_objects size: 12
added a new object
about to add a new object
current simple_objects size: 13
added a new object
about to add a new object
current simple_objects size: 14
added a new object
about to add a new object
current simple_objects size: 15
added a new object
about to add a new object
current simple_objects size: 16
added a new object
about to add a new object
Segmentation fault: 11
程序可以在这里测试:https://www.onlinegdb.com/rJHSik8Hf
什么原因导致分段错误以及如何防止它?
问题是您在使用 class 时重新分配 (copy/move)。
我猜向量分配了 16 个槽。现在您要添加项目 17。这意味着向量需要分配更大的数组和 copy/move 现有项目。
可行,但请考虑当前项目 (this)。它在旧数组中。它是 moved/copied 并且旧数组被破坏了。所以这现在指向你刚刚释放的内存并且你得到段错误(幸运)。
您可能想要的是调整向量的大小不会改变项目。您可以将项目包装在 std::unique_ptr 中,这样就可以正常工作。
其他替代方法是固定数组的大小以便不调整大小,或者不从数组中的对象修改数组。
在堆栈上创建 shared_ptr
的本地副本应该可以解决问题。 (只是 ptr,不是整个向量)
void grow () {
auto localObjects = objects;
std::cout << "growing" << std::endl;
for (int i { 0 }; i < 10; ++i) {
std::cout << "about to add a new object" << std::endl;
std::cout << "current simple_objects size: " << localObjects->size() << std::endl;
localObjects->push_back(SimpleClass(objects));
std::cout << "added a new object" << std::endl;
}
}
您还应该在迭代时创建一个副本,因为您在迭代时修改向量。
您的代码 运行 现在没有段错误。 https://onlinegdb.com/H1lNlcgOSG
auto localCopy = *simple_objects;
for (auto &obj: localCopy) {
obj.grow();
}
我有这个示例程序。我想要做的就是在 vector 本身包含的对象之间共享一个 vector 实例,以便它们可以从容器中操作(添加其他对象,删除它们自己)。
#include <iostream>
#include <memory>
#include <vector>
class SimpleClass {
private:
std::shared_ptr<std::vector<SimpleClass>> objects;
public:
SimpleClass (std::shared_ptr<std::vector<SimpleClass>> _objects): objects { _objects } {}
void grow () {
std::cout << "growing" << std::endl;
for (int i { 0 }; i < 10; ++i) {
std::cout << "about to add a new object" << std::endl;
std::cout << "current simple_objects size: " << objects->size() << std::endl;
objects->push_back(SimpleClass(objects));
std::cout << "added a new object" << std::endl;
}
}
};
int main () {
auto simple_objects = std::make_shared<std::vector<SimpleClass>>();
for (int i { 0 }; i < 10; ++i) {
simple_objects->push_back(SimpleClass { simple_objects });
}
std::cout << "simple_objects size: " << simple_objects->size() << std::endl;
for (auto &obj: *simple_objects) {
obj.grow();
}
return 0;
}
经过一些迭代后,程序存在 Segmentation Fault 11
:
simple_objects size: 10
growing
about to add a new object
current simple_objects size: 10
added a new object
about to add a new object
current simple_objects size: 11
added a new object
about to add a new object
current simple_objects size: 12
added a new object
about to add a new object
current simple_objects size: 13
added a new object
about to add a new object
current simple_objects size: 14
added a new object
about to add a new object
current simple_objects size: 15
added a new object
about to add a new object
current simple_objects size: 16
added a new object
about to add a new object
Segmentation fault: 11
程序可以在这里测试:https://www.onlinegdb.com/rJHSik8Hf
什么原因导致分段错误以及如何防止它?
问题是您在使用 class 时重新分配 (copy/move)。
我猜向量分配了 16 个槽。现在您要添加项目 17。这意味着向量需要分配更大的数组和 copy/move 现有项目。
可行,但请考虑当前项目 (this)。它在旧数组中。它是 moved/copied 并且旧数组被破坏了。所以这现在指向你刚刚释放的内存并且你得到段错误(幸运)。
您可能想要的是调整向量的大小不会改变项目。您可以将项目包装在 std::unique_ptr 中,这样就可以正常工作。
其他替代方法是固定数组的大小以便不调整大小,或者不从数组中的对象修改数组。
在堆栈上创建 shared_ptr
的本地副本应该可以解决问题。 (只是 ptr,不是整个向量)
void grow () {
auto localObjects = objects;
std::cout << "growing" << std::endl;
for (int i { 0 }; i < 10; ++i) {
std::cout << "about to add a new object" << std::endl;
std::cout << "current simple_objects size: " << localObjects->size() << std::endl;
localObjects->push_back(SimpleClass(objects));
std::cout << "added a new object" << std::endl;
}
}
您还应该在迭代时创建一个副本,因为您在迭代时修改向量。 您的代码 运行 现在没有段错误。 https://onlinegdb.com/H1lNlcgOSG
auto localCopy = *simple_objects;
for (auto &obj: localCopy) {
obj.grow();
}