如果使用 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;  

池化类分配多个对象。
池化类不介意解除分配。

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

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

解决方法

来自: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)operator new(size_t,std::nothrow_t) 的标准库实现中获得的指针。

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

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

关于参考信息的注意事项

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