C++:在以下情况下,内存会泄漏吗?

C++: Will the memory leak in the following situations?

本文关键字:内存 泄漏 情况下 C++      更新时间:2023-10-16

标题是问题。

我仍然不太了解动态分配的存储的行为。

#include <utility>
int main() {
    // Case 1:
    volatile char *c1 = new char; // I'm gonna make these volatile, so the compiler won't change the code.
    volatile char *d1 = c1;
    delete d1;
    // Case 2:
    volatile char *c2 = new char[4];
    volatile char *d2 = c2;
    delete []d2;
    // Case 3:
    volatile char *c3 = new char;
    volatile char *d3 = std::move(c3);
    delete d3;
    // Case 4:
    volatile char *c4 = new char[4];
    delete c4++;
    delete []c4;
    // Case 5:
    volatile char *c5 = new char[4];
    for (int i = 0; i < 4; ++i)
        delete c5++;
    return 0;
}

在每种情况下内存会泄漏吗?

案例 1 到 3:无泄漏。

案例 4 和 5;交易分配导致未定义的行为。您正在从不具有最初分配的值的指针中删除。

为什么 1 到 3 没有泄漏?您将适当的deletedelete[]与使用的newnew[]相匹配;它们成对匹配,每个分配一个取消分配。

我假设该示例很简单,用于演示分配,但请注意,指针不会"重置"为 NULL(或nullptr),因此一旦解除分配,对先前分配的内存的任何访问都是不确定的。


std::move的旁注,它是否使c3指针nullptr?不,它没有。std::move实际上并没有"移动"任何东西,它只是更改了值类别,请参阅此答案和一些示例代码。

情况 4 和 5 是未定义的行为,因此无法确定内存是否泄漏。

对于其他情况,内存不会泄漏。但是,值得一提的是,使用 newdelete 真的很糟糕,您应该始终使用资源管理类来保存内存。或者更简单地说,你一开始就不需要问这个问题。

在我看来,

您假设new char[5]为单个char执行 5 个单独的new。 (对我来说,这似乎解释了为什么你想出案例 4 和 5)。

但事实并非如此;例如,c4指向单个分配的存储块,该块(至少)足够大,可以容纳 4 char秒。 您不能删除其中的单个部分,只能删除所有部分。

new/deletenew[]/delete[] 之间的区别在C++超级常见问题解答中得到了很好的解释。

在您的程序中:

// Case 1:
volatile char *c1 = new char; // Allocates enough space for 1 char
volatile char *d1 = c1;
delete d1;                    // Frees the space allocated
// Case 2:
volatile char *c2 = new char[4]; // Allocates enough space for a 4-char array
volatile char *d2 = c2;
delete []d2;                     // Frees that space
// Case 3:
volatile char *c3 = new char;    // Same as in case 1
volatile char *d3 = std::move(c3); // c3 is not nullptr
delete d3;                       // Same as in case 1
// Case 4:
volatile char *c4 = new char[4]; // Same as in case 2
delete c4++;                     // should be delete[], then same as case 2
delete []c4;                     // undefined behavior
// Case 5:
volatile char *c5 = new char[4]; // Same as in case 2
for (int i = 0; i < 4; ++i)
    delete c5++;                 // doesn't make sense, undefined behavior
return 0;

情况 1:

volatile char *c1 = new char; 
volatile char *d1 = c1;
delete d1;

无内存泄漏。您正在分配内存,并c1指向它。然后发生指针c1的副本(而不是数据)。所以 d1 指向c1现在指向的同一个地方。然后,删除d1等于删除c1

案例2:

volatile char *c2 = new char[4];
volatile char *d2 = c2;
delete []d2;

与上述相同,只是您正在分配一个内存序列并删除一个内存序列。所以,没有泄漏。

案例3:

volatile char *c3 = new char;
volatile char *d3 = std::move(c3);
delete d3;

您首先分配一个内存并向其c3点。现在,您调用了move操作。此move操作将移动c3持有的地址d3,而不会对实际数据进行任何更改或移动或复制。之后,您删除了实际上指向c3指向同一位置的d3。所以,没有泄漏。

案例4&5:未定义的行为,如其他答案所述。