C :动态分配的变量未在clang中删除

C++: Dynamically allocated variables not deleted in Clang

本文关键字:clang 删除 变量 动态分配      更新时间:2023-10-16

沃尔特·萨维奇(Walter Savitch(的`````````''''c 解决问题,第9版'''

将删除应用于指针变量时,它指向的动态变量将被破坏。在这一点上,指针变量的值是未定义的,这意味着您不知道它在哪里,也不知道该值指向的位置。此外,如果某些其他指针变量指向被破坏的动态变量,则此其他指针变量也不确定。

但是,在clang-902.0.39.1下,删除指针并不会阻碍我使用该变量的能力。这是一个简短的例子,证明了这种行为:

int *p1, *p2;
p1 = new int(3);
p2 = p1;
cout << *p1 << endl << *p2 << endl;
delete p1;
cout << *p1 << endl << *p2 << endl;

使用此代码,我在单独的行上的输出为4 3 s。我希望在delete p1;之后引用p1p2时会发生错误,我应该不?

在Visual Studio的C 编译器下,引用p2输出了一个大的负数,表明我们引用了不属于我们的内存,并且访问p1导致程序崩溃。

我希望在删除P1之后引用P1和P2时会发生错误?

不一定。

在这一点上,指针变量的值不确定

不确定的(如在delete(被调用后使用指针可能会导致任何事情发生,好,坏或中立。

编译器不需要为进一步使用指针施加任何运行时障碍。特别是,不需要立即结束该程序。当然,一个好的编译器(带有正确的设置(可能会警告您,如果您的代码重复使用已删除的指针。

在Visual Studio的C 编译器下,引用P2输出一个较大的负数,表明我们引用了不属于我们的内存,并且访问P1导致程序崩溃。

特定的编译器可以创建一个过程,该过程在特定的操作系统上,在特定的内存负载条件下会导致崩溃。或者可能没有。同样,也不需要与指针相关的内存中充满垃圾数据。

尤其是,我相信调试构建中的Visual Studio可能会启动指针的内存,以便进一步使用导致崩溃/异常。这对于讨论会很有用。

除了调试构建外,唯一可能导致的问题是偶然的。考虑带有delete的指针的以下可能性,然后重复使用:

  • 该过程已将内存发布到操作系统。您的程序现在正在尝试访问它没有权利的内存。SEGFAULT(崩溃(。
  • 在内部,内存已被标记为属于其他变量(即程序的其他部分称为new或类似部分(,并且已写入。它似乎充满了垃圾数据。根据您的程序使用该变量的方式,可能会有或可能没有问题。它可能崩溃,可能打印出乱码的文字,等等。
  • 在内部,内存被标记为已删除,但程序的其他部分都不需要它。目前,记忆未触及。这就是您在Clang下看到的。

简而言之,同时预测已删除指针的内存会发生什么是棘手的,而对程序员的唯一责任是:不要再次使用它。

当您删除指针时,内存仍然存在,并且指针仍然指向它。但是,您不能保证它仍然有效,或者将来仍然存在。内存分配(new/malloc/etc(已将其标记为不再使用的内存中的位置,因此它可以重新分配或在页面上释放所有内存,此时访问它将导致访问访问权限(segfault(。

例如,如果我使用指针创建三个新的INT,则可能会将它们放置在内存中。如果我删除中间指针,则其地址仍然有效,因为在所有内存不再有效之前,无法释放内存页面。但是,即使我 can 访问现在已删除的指针的内存,但我不应该。那是因为如果我创建一个新的INT指针,它可能会分配给该新位置。

错误的隐喻:内存就像教室里的座位一样。有些人需要更多的座位(或抬起脚或放袋(,有些人需要更少的座位。在教室中的所有座位都是免费的之前,您不能从学校中删除教室。如果您要求被分配一个座位,则可能会获得Room1,Seat2。如果您放弃该座位(例如删除指针(,即使它不再是您的,您仍然可以参考Room1/seat2。如果您尝试坐在其中,您可能会发现其他人已经被分配了。如果您坐在其中,教室可能会随时关闭,因为您说您已经完成了座位。

座=您的指针指向

的内存

classroom =内存的页面

您的指针仍指向旧位置,仅此内存不再属于它们。后来可能还有另一个数据。因此,它不是稳定的输出。

内存已发布,但是您的指针仍指向数据过去的位置。