使用unique_ptr处理已分配数组时避免内存泄漏和未定义行为
2024-03-28 03:25:06
如何使用 unique_ptr
正确处理已分配数组
背景
unique_ptr
是一个非常有用的 C++ 标准库类,它使我们能够管理指向自由存储器分配对象的唯一指针。然而,当我们尝试使用 unique_ptr
来管理动态分配的数组时,可能会遇到内存泄漏和未定义行为。
问题
问题在于 unique_ptr
的析构函数会调用 std::default_delete<unsigned char>
,而该函数预期的是一个指向单个元素的指针,而不是一个指向数组第一个元素的指针。这会导致 Valgrind 报告内存泄漏和未定义行为。
解决方案
解决此问题的正确方法是使用 make_unique
函数来创建 unique_ptr
。make_unique
函数能够正确处理数组的情况,它会生成一个指向数组第一个元素的 unique_ptr
,并确保在 unique_ptr
的析构函数中正确调用 delete[]
来释放数组。
以下是如何使用 make_unique
函数创建 unique_ptr
的示例代码:
#include <memory>
#include <string.h>
using namespace std;
int main()
{
unique_ptr<unsigned char[]> testData = make_unique<unsigned char[]>(16000);
memset(testData.get(), 0x12, 0);
return 0;
}
总结
要正确创建持有在自由存储器上分配的数组的 unique_ptr
,请使用 make_unique<unsigned char[]>(16000)
。这将确保 unique_ptr
的析构函数以正确的方式释放数组。
常见问题解答
-
为什么在使用 Visual Studio 2013 时没有这个问题?
Visual Studio 2013 的标准库有一个错误,它允许unique_ptr
正确处理数组。在较新的编译器中,此错误已得到修复。 -
为什么
std::default_delete<unsigned char>
期望一个指向单个元素的指针?
std::default_delete
是一个通用函数,它可以删除任何类型的对象。但是,它假设被删除的对象是一个单个元素,而不是一个数组。 -
我可以使用
new
运算符直接创建unique_ptr
来处理数组吗?
不可以。new
运算符无法生成指向数组的unique_ptr
。必须使用make_unique
函数。 -
除了
make_unique
,还有其他方法来解决此问题吗?
有,但是make_unique
是最简单、最可靠的方法。 -
何时应该使用
make_unique
来创建unique_ptr
?
应该始终使用make_unique
来创建持有动态分配对象的unique_ptr
,无论该对象是单个元素还是数组。