【问题标题】:C++17 can the 'new' operator still leak memory?C ++ 17 'new' 运算符仍然可以泄漏内存吗?
【发布时间】:2020-10-20 19:06:42
【问题描述】:

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

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

后来,有人告诉我,如果我这样做而不删除,我会泄漏内存。我用 Visual Studio 2017 Professional 调试了我的程序,我的内存一直保持不变,无论我创建这个缓冲区多少次。

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

【问题讨论】:

  • 你没有泄露内存,你泄露了地址空间。如果您想泄漏内存,请尝试for(;;) new char;
  • 顺便说一句,这不是错误,因此不涉及“修复”。
  • @Joshua 以前从未听说过“泄露的地址空间”这个词,这是什么意思?对我来说,这看起来像是经常性的内存泄漏。
  • @HolyBlackCat:如果您分配大块而不写入它,则实际上还没有分配内存,只有地址空间。大块由内存映射分配。
  • @HolyBlackCat 据我所知,两者在 C++ 中没有区别。据我了解,在第一次写入之前不提交内存的平台上可能存在差异。因此,在您尝试访问该对象之前,该地址将被保留,但尚未将其内存提交给您的进程。这些平台与 C++ 不兼容,但假装不兼容。

标签: c++ c++17 new-operator


【解决方案1】:

在没有delete[] 的情况下调用new[] 确实会泄漏内存。除非您泄漏了大量缓冲区,否则您可能看不到它,这取决于您应用的 RTL 如何在后台分配/缓存内存。

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

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

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

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

【讨论】:

    【解决方案2】:

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

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

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

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

    1. 您的内存分配器向操作系统请求内存。
    2. 您的内存分配器返回一个指向部分内存的指针。

    (严格来说,这不是特定于您的编译器,这是基于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。因此,您有空间执行new 并在该内存缓冲区内接收分配,而无需更改进程的操作系统级内存占用。

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

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

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

    【讨论】:

      猜你喜欢
      • 2021-05-08
      • 2013-04-20
      • 2012-03-04
      • 2011-05-15
      • 1970-01-01
      • 2011-04-17
      • 2021-08-06
      • 2013-11-10
      • 1970-01-01
      相关资源
      最近更新 更多