使用unique_ptr管理自定义node结构体时出作用域崩溃问题排查
问题分析:std::unique_ptr退出作用域时崩溃的原因
崩溃根本原因:违反ODR单一定义规则
C++的ODR(单一定义规则)要求,整个程序中同一个实体(比如结构体、函数)只能有唯一且一致的定义。你的项目里存在两个完全不同的node结构体定义:
test.cpp中的node仅包含一个std::string成员,还有自定义的构造、析构函数another.cpp中的node包含double、std::string、两个指针成员,无自定义析构
编译阶段每个cpp文件各自处理不会报错,但链接器合并目标文件时,会把同名的node相关符号(比如类型内存布局、析构函数地址)强行合并。链接器无法区分两个不同的node,会随机选用其中一个的定义。
当test.cpp里用std::make_unique<node>创建对象时,是按照自身node的内存大小分配空间,但退出作用域时,unique_ptr调用的析构函数可能对应另一个node的定义,或者按照另一个node的内存布局清理对象——这就会访问到超出当前对象范围的内存,直接触发0xc0000005内存访问违规异常。
std::unique_ptr的使用是否有误?
你的unique_ptr写法完全没问题:
std::make_unique<node>("root")正确创建node对象并交由unique_ptr管理- 代码块退出时
unique_ptr自动释放对象的逻辑是标准用法
崩溃和unique_ptr的使用无关,纯粹是ODR违规导致的连锁问题。
复现代码
test.cpp
#include "fmt/core.h" #include <memory> #include <string> struct node{ std::string str; explicit node(const std::string& str): str(str) { fmt::print(" construct node: {}\n", this->str); } ~node(){ fmt::print(" deconstruct node: {}\n", str); } }; bool test(){ { auto str{std::make_unique<std::string>("str")}; } // 此处无问题 { auto root = std::make_unique<node>("root"); fmt::print("str: {}\n", root->str); } // 此处崩溃 return true; }
main.cpp
bool tree_test(); bool test(); int main() { //bree_test(); //tree_test(); test(); return 0; }
another.cpp中的node定义
struct node{ double p; std::string str; bnode* left; bnode* right; };
内容的提问来源于stack exchange,提问作者Kera
相关产品推荐
相关产品推荐

