如何测试自定义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
相关产品推荐
相关产品推荐

