C++17 的 'new' 运算符还能泄漏内存吗?

C++17 can the 'new' operator still leak memory?

我正在做一个项目,需要一个字符缓冲区来通过网络发送结构。我正在使用:

char* buf = new char[sizeof(obj)];

后来有人告诉我,如果我不删除就那样做会泄漏内存。我用 Visual Studio 2017 Professional 调试了我的程序,无论我做了多少次缓冲区,我的记忆都保持不变。

我的问题是:C++17 是否修复了 'new' 运算符可能导致的内存泄漏问题,或者这是我正在使用的编译器特有的问题?提前致谢!

在没有delete[]的情况下调用new[]确实会泄漏内存。除非你泄漏了大量缓冲区,否则你可能看不到它,这取决于你的应用程序的 RTL allocates/caches 内存在引擎盖下的方式。

传统上,使用 std::vector<char>,甚至 std::string 是动态缓冲区的首选,让它们为您处理自己的内存,例如:

std::vector<char> buf(sizeof(obj));
or
std::string buf(sizeof(obj), 0);

如果您出于某种原因绝对需要 new[]/delete[],请考虑使用 std::unique_ptr<char[]>,让它为您调用 delete[],例如:

std::unique_ptr<char[]> buf(new char[sizeof(obj)]);
or
auto buf = std::make_unique<char[]>(sizeof(obj));

是的,这看起来像是内存泄漏。

如果不想在动态分配的内存上显式调用delete,标准的解决方案是使用智能指针,通常使用“引用计数”来de-allocate安全记忆。

有关智能指针的更多信息:What is a smart pointer and when should I use one?

至于为什么你没有分配更多的内存——你在测量什么?通常会发生两种“分配”:

  1. 您的内存分配器从操作系统请求内存。
  2. 你的内存分配器 returns 指向那部分内存的指针。

(严格来说,这不是特定于您的 编译器 ,这是基于 new 的实现。如果您使用的是标准 Visual C++ 工具链,那么从这个意义上说,是的,new 的实现依赖于 Visual C++。这里是一个起点:https://docs.microsoft.com/en-us/cpp/standard-library/memory?view=vs-2019)

您可能正在测量 #1 -- 操作系统分配了多少内存。例如,sizeof(obj) 可能是 1 KB,而您的分配器可能已从操作系统请求 256K。因此,您 space 可以执行 new 并在该内存缓冲区中接收分配,而无需更改进程的 OS-level 内存占用。

作为实验,我建议连续分配更大的内存块:

const int alloc_size = 4; // then 5, 6, 7...
for (int i = 0; i < (2<<alloc_size); i++) {
  // do your allocation here
}

然后找出在测量值发生变化之前您可以执行多少次分配。