You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 08:05:25