【问题标题】:Deallocating a `char*` with `delete` - memory leak?用`delete`释放`char*` - 内存泄漏?
【发布时间】:2014-06-10 12:52:54
【问题描述】:
template<typename T> char* allocateSomething()
{
    return reinterpret_cast<char*>(std::allocator<T>{}.allocate(1));
}

void deallocateSomething(char* mPtr) { delete mPtr; }

struct TestType { ... };

int main()
{
    char* ptr{allocateSomething<TestType>()};
    deallocateSomething(ptr);   
    return 0;
}

是否保证deallocateSomething(ptr) 将释放所有分配的字节,即使它不知道调用allocateSomething&lt;T&gt;() 时使用的typename T

或者是否也需要模板化deallocateSomething

编辑:我手动处理对象的构造/销毁。


编辑 2:这会正常工作吗?

template<typename T> char* allocateSomething()
{
    return reinterpret_cast<char*>(std::malloc(sizeof(T)));
}

void deallocateSomething(char* mPtr) { std::free(mPtr); }

// ...

【问题讨论】:

  • 指针的值未指定,删除未指定的指针具有未定义的行为。
  • @user2079303:是什么让您认为它未指定? char* 在处理内存方面非常特别。
  • @MatthieuM,标准让我这么认为:“reinterpret_cast 执行的映射可能会或可能不会产生与原始值不同的表示。”如果标准以其他方式保证 reinterpret_castchar* 不会产生不同的表示,那么我同意可以保证该值是明确定义的。
  • @VittorioRomeo:我也不太明白……
  • @VittorioRomeo,我只能推测人们对行为未定义的代码投了反对票……当问题的目的是询问代码是否正常时,这似乎不公平。

标签: c++ memory c++11 memory-management


【解决方案1】:

是否保证 deallocateSomething(ptr) 将释放所有分配的字节,即使它不知道调用 allocateSomething() 时使用的类型名 T?

不,没有任何保证,这是未定义的行为。

或者是否也需要模板化 deallocateSomething?

一般来说是的。

您必须使用匹配的分配/解除分配方法。如果你想用delete 解除分配,那么你必须用new 分配。如果您更改分配使其不使用std::allocator(您无法控制也不知道它是如何分配的)而是使用new char[sizeof(T)] 进行分配,那么您可以使用delete[] 安全地解除分配(但不是delete!你必须使用[])

【讨论】:

  • 将使用std::mallocstd::free 代替new/delete 保证内存将被正确释放?据我所知,mallocfree 对类型一无所知。我手动处理构造/破坏,所以我不在乎。
  • 是的,或者匹配new/delete,正如我在回答中解释的那样。任何匹配的分配函数对都可以,但不能将mallocfree()std::allocatordelete 混合使用
  • @VittorioRomeo:您确实可以使用mallocfree,尽管使用new[]delete[]char 的效果一样好(实际上,它可能会产生相同的效果)代码)。您确实需要担心 alignment,但通用分配函数只能保证对齐到 alignof(std::max_align_t),因此对于具有更大对齐的类型,您可能会遇到问题。
  • @MatthieuM.: 你能告诉我new[]/delete[] 版本的正确代码是什么吗?我是否必须分配大小为sizeof(T)char[] 缓冲区?谢谢。
  • @MatthieuM。 new char[]delete [] 可以使用,但会产生误导。在 C++ 中获取原始内存的正常方法是调用operator new() 函数,然后调用operator delete 将其删除。
【解决方案2】:

您必须使用匹配分配和空闲功能。即。

  • mallocfree
  • newdelete
  • new[]delete[]
  • std::allocator&lt;&gt;::allocatestd::allocator&lt;&gt;::deallocate。这里指定默认版本使用new/delete,但没有指定它是否进行一些分配分组(例如它可能低于某个大小而不是高于某个大小),所以你可以做什么一个实现,而不是另一个。

【讨论】:

    猜你喜欢
    • 2019-02-27
    • 2012-06-08
    • 2011-01-27
    • 2010-11-19
    • 2014-08-26
    • 1970-01-01
    • 2018-06-04
    • 2014-09-19
    • 2010-12-04
    相关资源
    最近更新 更多