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

如何测试自定义unique_ptr超出作用域时指针已被正确释放?

测试自定义unique_ptr的内存释放逻辑

要验证自定义unique_ptr在超出作用域时正确释放内存,核心思路是追踪对象的生命周期或内存释放动作,避免直接访问已释放的内存(那属于未定义行为)。以下是两种可靠的实现方式:

方法一:使用带生命周期追踪的测试类

给测试用的类添加静态计数器,记录构造和析构的次数,通过对比两者是否相等来验证对象是否被正确销毁(内存随之释放)。

class TrackedFoo {
public:
    static inline size_t construct_count = 0;
    static inline size_t destruct_count = 0;

    TrackedFoo() { construct_count++; }
    ~TrackedFoo() { destruct_count++; }
};

TEST(unique_ptr_test, releases_memory_on_scope_exit) {
    // 重置计数器,避免其他测试用例的干扰
    TrackedFoo::construct_count = 0;
    TrackedFoo::destruct_count = 0;

    {
        // 创建局部作用域的unique_ptr
        unique_ptr<TrackedFoo> ptr(new TrackedFoo);
        // 验证对象已构造
        ASSERT_EQ(TrackedFoo::construct_count, 1);
        ASSERT_EQ(TrackedFoo::destruct_count, 0);
    }

    // 作用域结束后,构造次数应等于析构次数,说明对象被销毁
    ASSERT_EQ(TrackedFoo::construct_count, TrackedFoo::destruct_count);
}

方法二:重载全局delete运算符(仅限测试环境)

在测试文件中临时重载全局delete运算符,用计数器记录内存释放的次数,验证unique_ptr是否在生命周期结束时调用了delete。

namespace test_utils {
    static inline size_t delete_call_count = 0;
}

// 重载全局delete,记录调用次数后实际释放内存
void operator delete(void* ptr) noexcept {
    test_utils::delete_call_count++;
    std::free(ptr);
}

TEST(unique_ptr_test, calls_delete_on_scope_exit) {
    test_utils::delete_call_count = 0;

    {
        unique_ptr<int> ptr(new int(42));
        // 此时delete还未被调用
        ASSERT_EQ(test_utils::delete_call_count, 0);
    }

    // 作用域结束后,delete应被调用一次
    ASSERT_EQ(test_utils::delete_call_count, 1);
}

注意事项

  • 方法一的隔离性更好,仅针对测试类生效,不会影响其他测试的内存操作;
  • 方法二需要注意测试隔离,确保每个测试用例前重置计数器,避免不同用例互相干扰;
  • 绝对不要尝试访问已释放的内存(比如保存原始指针后在作用域外判断是否为nullptr),这属于未定义行为,无法保证测试结果的可靠性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 06:07:07