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

运行时特定节点内存泄漏排查:定位未释放的特定状态对象

定位状态切换中未释放的特定对象问题

需要找出应用状态切换过程中,仅由MakeState(0)创建且在MakeState(1)执行后未被删除的对象。尝试过Visual Studio内存堆分析工具,但无法精准筛选这类对象,实用性不足。

代码示例

#include <vector>
#include <map>

class MyClass {
public:
    int myNum;
};

std::vector<MyClass *> firstStateClasses;
std::map<int, MyClass *> stateClasses;

void MakeFirstState()
{
    for (int i = 0; i < 10; ++i)
    {
        MyClass* firstClass = new MyClass();
        firstStateClasses.push_back(firstClass);
    }
}

void DeleteFirstState()
{
    for (auto p : firstStateClasses)
    {
        delete p;
    }
    firstStateClasses.clear();
}

void MakeState(int state)
{
    MyClass* randomClass = new MyClass();

    stateClasses.insert(std::make_pair(state, randomClass));
}

void DeleteState(int state)
{
    auto itr = stateClasses.find(state);
    if (itr != stateClasses.end())
    {
        delete itr->second;
        stateClasses.erase(itr);
    }
}

int main()
{
    MakeFirstState();
    MakeState(0);
    //Leak is here, state wasnt deleted.
    MakeState(1);
    //I need to know here objects that were made only in MakeState(0) and not deleted.
    DeleteState(1);
    MakeState(2);
    DeleteState(2);
    DeleteFirstState();
}

解决方案

手动追踪(轻量精准)

1. 添加对象生命周期日志

给MyClass增加构造和析构函数,记录创建时的状态ID,运行时直接通过控制台输出定位未释放对象:

#include <iostream> // 新增头文件

class MyClass {
public:
    int myNum;
    int createState; // 记录对象所属的创建状态
    MyClass(int state) : createState(state) {
        std::cout << "创建状态" << state << "的MyClass,地址:" << this << std::endl;
    }
    ~MyClass() {
        std::cout << "销毁状态" << createState << "的MyClass,地址:" << this << std::endl;
    }
};

// 修改MakeState函数,传入state到构造函数
void MakeState(int state)
{
    MyClass* randomClass = new MyClass(state);
    stateClasses.insert(std::make_pair(state, randomClass));
}

运行程序后,对比创建和销毁日志,没有对应销毁记录的就是泄漏对象,一眼就能找到state 0的实例。

2. 直接检查存活对象

在需要排查的位置(比如MakeState(1)执行后),遍历stateClasses输出所有存活对象:

// 在main函数的指定检查点添加代码
//I need to know here objects that were made only in MakeState(0) and not deleted.
std::cout << "\n===== 当前未释放的状态对象 =====" << std::endl;
for (const auto& item : stateClasses) {
    std::cout << "状态ID:" << item.first << ",对象地址:" << item.second << std::endl;
}

这段代码会直接列出所有未被删除的对象,精准定位state 0的泄漏实例。

适配VS堆分析工具的方案

如果想用VS工具精准筛选,给MakeState创建的内存块打自定义标记:

#define STATE_ALLOC_MARKER 0x12345678

// 内存分配钩子函数,给指定内存打标记
int __cdecl AllocHook(int allocType, void* userData, size_t size, int blockType, long requestNumber, const unsigned char* filename, int lineNumber) {
    if (blockType == _CLIENT_BLOCK && userData != nullptr && *(int*)userData == STATE_ALLOC_MARKER) {
        // 设置自定义dump回调,方便筛选
        _CrtSetDumpClient([](void* data, size_t size) {
            std::cout << "这是MakeState创建的对象,大小:" << size << std::endl;
        });
    }
    return TRUE;
}

void MakeState(int state)
{
    int marker = STATE_ALLOC_MARKER;
    _CrtSetAllocHook(AllocHook); // 注册钩子
    MyClass* randomClass = new MyClass(state);
    _CrtSetAllocHook(nullptr); // 注销钩子
    stateClasses.insert(std::make_pair(state, randomClass));
}

之后用VS堆分析时,过滤带有自定义标记的内存块,再结合前后快照对比,就能精准找出MakeState(0)创建但未释放的对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 23:31:45