使用“new []”进行分配并仅使用“delete”进行删除时会发生什么情况

What happens on allocating with "new []" and deleting with just "delete"

提问人:mitesh 提问时间:9/16/2020 最后编辑:Ted Lyngmomitesh 更新时间:9/17/2020 访问量:77

问:

好的,所以我正在尝试使用 C++ 中的指针,因为我在休息了将近一年半后再次开始编码(学校的东西)。所以,如果这对你来说看起来很幼稚,请饶了我,我只是生锈了。

无论如何,我在 VS 2019 中搞砸了指针,我注意到一些开始困扰我的东西。

这是我写的代码:

#include <iostream>

int main() {
    int* i = new int[4];
    *i = 323;
    *(i + 1) = 453;
    std::cout << *i << std::endl;
    std::cout << *(i + 1) << std::endl;
    delete i;
}

有些奇怪,对吧?别担心,删除是故意的,这就是这个问题的重点。现在我预计它会造成一些内存事故,因为这不是我们删除堆上的数组的方式,令我惊讶的是,它没有(我在调试和发布中都这样做了,并且有相同的观察)

分配阵列:

第一次修改: enter image description here

第二次修改 enter image description here

现在我期待删除时发生某种事故,因为我没有按照应该删除的方式删除它。但

删除不正确

enter image description here

现在在另一次运行中,我实际上正确地使用了删除运算符,它做了同样的事情:

enter image description here

现在,当我尝试使用 malloc 进行分配并使用 delete 释放它时,我得到了相同的结果。

所以我的问题是 - 为什么我的代码不会搞砸?我的意思是,如果这就是它的工作方式,我可以只使用 delete(指针)来擦除整个数组。

我问题的要点是“新操作员在幕后做什么?

C++ 指针 malloc new-operator

评论

0赞 mitesh 9/17/2020
int main() { int* i = new int[4]; *i = 323; *(i + 1) = 453; std::cout << *i << std::endl; std::cout << *(i + 1) << std::endl; 删除 i; 返回 0; }
1赞 Eljay 9/17/2020
在我的机器上崩溃。我所看到的和你所看到的,都是由于未定义的行为而产生的合理结果。在两者之间,我认为我得到了更好的行为。
0赞 mitesh 9/17/2020
好的,所以我在 clang 上测试了代码,它只是删除了数组中的第一个整数,其余的保持不变
2赞 Daniel Langr 9/17/2020
发生的情况是不确定的。
1赞 Jesper Juhl 9/17/2020
我们的老朋友 Undefined Behaviour任何事情都是允许的 - 该程序根本无效。

答:

6赞 eerorika 9/17/2020 #1

使用“new []”进行分配并仅使用“delete”进行删除时会发生什么情况

程序的行为是未定义的。

现在我以为它会造成一些记忆事故

你的期望是错误的。未定义的行为并不能保证在记忆或其他方面发生事故。不能保证程序的行为。

我的意思是,如果这就是它的工作原理

这就是你观察它“工作”的方式。这并不意味着它一定会一直这样工作。欢迎来到未定义的行为。

评论

0赞 mitesh 9/17/2020
好的,所以我在 clang 上测试了它,它只是删除了数组中的第一个元素(它应该如此),那么这个行为编译器是特定的吗?
3赞 eerorika 9/17/2020
(as it should)当行为未定义时,程序“应该”没有行为。 任何事情,都可能影响未定义的行为。这包括编译器、操作系统、CPU、月相和你的邻居。此外,即使在完全相同的条件下,行为也可能不同。So is this behavior compiler specific?
2赞 Galik 9/17/2020
@mitesh 它是未定义的,这意味着编译器可以做任何他们想做的事情。从一个编译器版本到另一个编译器版本,行为可能会发生变化,只需使用不同的编译器标志即可更改。对于使用相同标志的相同编译器版本,它可能会发生变化,但在不同的架构/操作系统等上。
1赞 Qix - MONICA WAS MISTREATED 9/17/2020
@mitesh直接回答您的问题,是的,它是特定于编译器的。它也可以是特定于日期的、特定于天气的,或者编译器甚至可以发出使用发射代码炸毁外国的代码。所有这些都不比另一个更有效或更无效。这就是未定义的行为。