【问题标题】:Potential Mem leak: Malloc for block and free for parts of the block?潜在的内存泄漏:块的 Malloc 和部分块的空闲?
【发布时间】:2020-03-17 06:34:46
【问题描述】:

我正在使用遗留的 C++ 代码,该代码使用 malloc 保留一块内存并将其划分为单独释放的部分。像这样的:

const int N_floats_per_buffer = 100;
const int N_buffers = 2;
//reserve buffers en bloque
float * buffer = (float*) malloc(N_float_per_buffer * N_buffers * sizeof(float));
//then this block memory is divided into sub-blocks
float * sub_buffer[N_buffers];
for(int j = 0; j < N_buffers; ++j)
{
    sub_buffer[j] = buffer + j*N_floats_per_buffer;
}
//do something with the buffers...
//...
//finally: memory is freed for the individual buffers
for(int j = 0; j < N_buffers; ++j)
{
    if(sub_buffer[i]!=NULL) free(sub_buffer[j]);
}

在实际代码中实际上更令人困惑,但我想我已经抓住了它的精髓。

我的问题是:这是内存泄漏吗?

【问题讨论】:

  • free 的使用无效:您只能使用 free 已有的 malloced(calloced,strduped,...)。您的 sub_buffers 是指向现有内存的指针,而不是分配内存的句柄。但是你应该在完成后free(buffer)
  • @walnut 我删除了 C 标记,因为代码是使用 MSVC 版本 1900 编译的。关于可变长度数组:我输入错误并忘记了整数长度变量前面的 const。我在编辑中更正了它。这是你的意思吗?
  • @geo 是的,这就是我的意思。 const 解决了,是的。

标签: c++ memory-leaks malloc free


【解决方案1】:

这不是内存泄漏。更糟糕的是,未定义的行为。

您只能在从malloc(或calloc 等)返回的指针上调用free。您不能在指向返回存储块中其他位置的指针上调用free。这样做会导致未定义的行为。


同样在更迂腐的一面,malloc 不创建任何对象,并且指针算法需要指针指向数组对象的元素,以便它在 C++ 中具有明确定义的行为。因此,从技术上讲,当您这样做时,您已经有未定义的行为

buffer + j*N_floats_per_buffer

尽管可能所有编译器的行为都符合预期(即使标准没有做出任何保证)。这个问题最近才在 C++20 中得到解决,其中所需的数组将被隐式创建。

在 C++ 中几乎总是只使用new/delete,而不是malloc/free

【讨论】:

  • 我刚刚阅读了 cppreference (en.cppreference.com/w/c/memory/free) 上的“免费”。它说:“如果 ptr 的值不等于 malloc()、calloc()、realloc() 或 aligned_alloc()(自 C11 起)先前返回的值,则行为未定义。”这绝对是你所说的好。我唯一想知道的是(自 C11 以来)附件。这是否意味着在 C11 之前它不是未定义的行为?
  • 还有一个问题:如果仅释放数组的第 0 个元素,它是否也是未定义的行为:free(sub_buffer[0]) 在这种情况下,它将指向由分配的块malloc,还是没有? (我知道这仍然是糟糕的代码)
  • @geo 如果您正在编写 C++ 代码,首先应该查看页面的 C++ 版本:en.cppreference.com/w/cpp/memory/c/free。 “(since C11)”注释仅适用于“,或aligned_alloc()”部分。 (文本周围应该有一个框来表示)。那是因为aligned_alloc() 仅使用 C11 添加到 C 标准中。在以前的迭代中它不存在。句子的其余部分始终适用。在 C++ 页面上,您将看到 C++ 的等效项。
  • @geo 如果你只释放sub_buffer[0](并且只有一次),那么没有问题。 sub_buffer[0] 指向与从malloc 返回的指针相同的地址。 free 上不会有未定义的行为,在这种情况下不会有任何内存泄漏。我关于指针算术未定义行为的其他说明仍然适用,但这并不是真正的实际问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-26
相关资源
最近更新 更多