c++ - 使用 shared_ptr 的引用时的 SIGSEGV
问题描述
如果您运行以下 C++ 代码,您将获得一个 SIGSEGV:
#include <iostream>
#include <vector>
#include <memory>
class Node {
public:
std::vector<std::shared_ptr<Node>> childNodes;
};
void addChild(const std::shared_ptr<Node> &node, std::shared_ptr<Node> &parentNode) {
std::shared_ptr<Node> newNode = std::make_shared<Node>();
std::cout << node->childNodes.size() << std::endl;
parentNode->childNodes.push_back(newNode);
std::cout << node->childNodes.size() << std::endl; // the program crashes when running this line
}
int main(int argc, char *argv[]) {
std::shared_ptr<Node> parentNode = std::make_shared<Node>();
parentNode->childNodes.emplace_back(std::make_shared<Node>());
std::shared_ptr<Node>& childNode = parentNode->childNodes[0];
addChild(childNode, parentNode);
return 0;
}
我不知道它为什么会崩溃。但是我发现如果我在主函数中更改了这一行:
std::shared_ptr<Node>& childNode = parentNode->childNodes[0];
到
std::shared_ptr<Node> childNode = parentNode->childNodes[0];
问题就会消失。程序正确输出两个零并安全退出,为什么?是什么导致了最初的崩溃以及为什么修改可以修复它?
解决方案
A push_back
into a vector 使所有迭代器、指针和对向量现有元素的引用无效。
由于node
是对 的元素的引用parentNode->childNodes
,因此推入它会使该引用无效。所以仅仅访问node->childNodes.size()
是未定义的行为。
当您在向量中使用元素的副本时,node
引用仍然有效,因为shared_ptr
它所引用的仍然存在,在向量管理的存储之外。
您还可以shared_ptr
通过简单地将引用传递给节点本身来避免复制。IE
void addChild(const Node &node, std::shared_ptr<Node> &parentNode)
即使任何 shared_ptr 被重新分配,对的引用Node
也不会失效。
推荐阅读
- database - Microsoft Access 数据库登录表单中的不匹配错误
- google-cloud-platform - 查询 Bigquery 重复字段
- python - 比较两个变量的最pythonic方法是什么?
- apache - Apache SVN 模块不在 Web 视图中列出许可的子文件夹
- laravel - 在 Laravel 5.6 项目中使用 xamp 的虚拟主机中的别名
- python - 为什么我的模型中的 post.post 没有以 html 显示?(邮政)
- java - Java异步方法执行
- swift - 使用 Swift 3 显示频谱图
- javascript - 谷歌云平台oauth窗口问题
- text-processing - 在 Python 中将数据输出顺序打印为格式化表