首页 > 解决方案 > 如果使用 delete 使用 malloc 解除分配的对象会发生什么

问题描述

如果使用 delete 释放使用 malloc 分配的对象会怎样?
我正在尝试制作 ObjectPool 系统。
所以我写了这段代码。

struct A
{
    int a;
    int b;
    int c;

    A()
    {
        std::cout << "A constructor" << std::endl;
    }
    ~A()
    {
        std::cout << "A destructor" << std::endl;
    }
};

A* a = (A*)std::malloc(sizeof(A) * 10);
    
A* a0 = a;
new (a0) A();
delete a0; 

A* a1 = a + 1;
new (a1) A();
delete a1;  

.
.
.

A* a9 = a + 9;
new (a9) A();
delete a9;  

Pooling Class 分配多个对象。
Pooling Class 不介意解除分配。

但我担心使用 delete 释放内存(使用 malloc 分配)可能会导致内存泄漏。此代码是否会导致内存泄漏?

我永远不会调用 std::free(a)。
让用户自己释放内存。

标签: c++c++11

解决方案


来自:https ://en.cppreference.com/w/cpp/memory/new/operator_delete :

如果传递给标准库释放函数的指针不是从相应的标准库分配函数中获得的,则行为未定义。

此外,对于第一个定义:

void operator delete  ( void* ptr ) throw();        (until C++11)
void operator delete  ( void* ptr ) noexcept;       (since C++11)

它说:

此函数的标准库实现的行为是未定义的,除非 ptr 是空指针或者是先前从operator new(size_t)or的标准库实现中获得的指针operator new(size_t, std::nothrow_t)

因此,这意味着如果使用new,则必须delete在该内存上使用,如果使用,malloc()必须在该内存上使用free(),否则行为未定义。

“未定义”并不意味着程序不起作用。这意味着语言定义没有指定会发生什么,因此它可能会或可能不会起作用,具体取决于您的编译器的实现。但是,你不能指望它工作,所以它被认为是一个错误,应该被修复。

关于参考信息的注意事项

https://en.cppreference.com/w/是一个任何人都可以编辑的 wiki。它不是官方标准,但它是我们所拥有的最接近的开源标准。另一个公共标准参考来源是http://www.cplusplus.com,它通常不是最新的,但是当它有解释时,我发现它们要好得多,因为它们更容易理解,但是有时更糟糕的是它们不完整或不涵盖 C++11 之后的最新版本的 C++。所以,两者一起使用。如果您正在寻找更迂腐和更新的解释,请更多地依赖 cppreference.com,如果您正在寻找更适合初学者且更易于理解的解释,请更多地依赖cplusplus.com,因为它的信息是完整的和最新的。


推荐阅读