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

C++多态调用函数时_vfptr为空(0xcccccccccccccccc)问题求助

解决C++多态调用时_vfptr为空(0xcccccccccccccccc)的问题

兄弟,你这问题我太熟了——本质就是悬空指针在搞鬼!咱们一步步拆解:

问题根源:局部对象销毁导致悬空指针

先看你TestApp::Init()里的这段代码:

void TestApp::Init() {
    RenderModels m(/* 参数省略 */);
    o.push_back(&m);
    // ...
}

这里的RenderModels m是栈上的局部变量,当Init()函数执行完退出时,栈上的局部变量会被系统自动销毁,内存被释放。但你把它的地址&m塞进了std::vector<Object*> o里,等后续OnRender()调用这个指针时,它指向的是已经被回收的内存——这就是典型的悬空指针。

VS调试器里显示的_vfptr = 0xcccccccccccccccc,还有成员变量c、b值乱变,都是VS在告诉你:这块内存已经不属于你的对象了,是无效内存。

解决方案:让对象生命周期足够长

要解决这个问题,你得确保RenderModels对象的生命周期能覆盖到OnRender()的调用时机,有两种常用方式:

1. 用动态分配(new)创建堆对象

把局部对象改成堆上分配,这样对象不会随函数结束而销毁:

void TestApp::Init() {
    // 先把设备和上下文指针提出来,代码更清晰
    auto device = Armageddon::Application::GetInstance()->GetWindow()->GetWindowGraphics()->GetComptrDevice();
    auto device_context = Armageddon::Application::GetInstance()->GetWindow()->GetWindowGraphics()->GetComptrDeviceContext();
    
    // 用new在堆上创建对象
    RenderModels* m = new RenderModels(device, device_context);
    o.push_back(m);
    
    Armageddon::Log::GetLogger()->trace("NAME : {0}", o[0]->GetName());
}

⚠️ 注意:堆对象需要手动释放,记得在TestApp的析构函数里清理,避免内存泄漏:

TestApp::~TestApp() {
    for (auto obj : o) {
        delete obj;
    }
    o.clear();
}

2. 用智能指针(更推荐,自动管理内存)

手动管理堆内存容易忘释放,推荐用C++的智能指针std::unique_ptr或std::shared_ptr,它会自动帮你释放对象:

首先修改TestApp的成员变量类型:

private:
    ImVec2 CurrentWindowSize;
    // 把普通指针改成unique_ptr的vector
    std::vector<std::unique_ptr<Object>> o;

然后修改Init()函数:

void TestApp::Init() {
    auto device = Armageddon::Application::GetInstance()->GetWindow()->GetWindowGraphics()->GetComptrDevice();
    auto device_context = Armageddon::Application::GetInstance()->GetWindow()->GetWindowGraphics()->GetComptrDeviceContext();
    
    // 用make_unique创建智能指针
    auto m = std::make_unique<RenderModels>(device, device_context);
    // 转移所有权到vector里
    o.push_back(std::move(m));
    
    Armageddon::Log::GetLogger()->trace("NAME : {0}", o[0]->GetName());
}

这样就不用手动写delete了,当TestApp销毁时,vector里的智能指针会自动释放对应的对象内存,省心又安全。

额外提醒:RenderModels里的引用成员要注意

另外,你的RenderModels类里有两个引用类型的成员:

private:
    Microsoft::WRL::ComPtr <ID3D11Device>& device;
    Microsoft::WRL::ComPtr <ID3D11DeviceContext>& device_context;

要确保你传入的ComPtr对象生命周期比RenderModels长,不然也会出现悬空引用的问题。不过目前你的核心问题是悬空指针,先解决这个再说。

内容的提问来源于stack exchange,提问作者Alexis

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 07:17:51