C ++:删除这个;返回x;

时间:2016-08-08 16:54:13

标签: c++ free

嘿,我对一些C ++行为感到好奇,因为如果这种行为是一致的,我正在处理的代码将从简单性方面受益匪浅。基本上我的想法是针对我的对象A中的特定函数来计算返回float的复杂计算,但在返回float之前,偶尔会调用delete this。< / p>

1

这是我尝试验证的功能的一致代码示例。

#include <iostream>
#include <stdio.h>
#include <cstdlib>

using namespace std;

struct A
{
    float test(float a) {delete this; return a;}
};

int main()
{
    A *a = new A();
    cout << a->test(1.f) << endl;
    cout << "deleted?" << endl;
    cout << a->test(1.f) << endl;
}

输出变为:

1.0
deleted?
*** Error in `./test': double free or corruption (fasttop): 0x0105d008 *** Aborted (core dumped)

我认为这意味着对象被正确删除了(内存中还剩下什么?一个不可召唤的A骨架?一个类型指针?一个空指针?),但我不确定我是否正确。如果是这样,这种行为是否一致(我的函数只会返回本机类型(浮动))

2

此外,我很好奇为什么这似乎不起作用:

struct A
{
    float test(float a) {delete this; return a;}
};

int main()
{
    A a;
    cout << a.test(1.f) << endl;
}

这会编译但在返回任何内容之前会抛出以下错误。

*** Error in `./test': free(): invalid pointer: 0xbe9e4c64 *** Aborted (core dumped)

注意请不要回答一长串解释,说明为什么这是错误的编码/礼仪或其他什么,不在乎,我只是对可能性。

2 个答案:

答案 0 :(得分:4)

成员函数调用delete this; 是安全的,如果您知道该对象是使用标量new分配的,并且之后没有其他任何内容可以使用该对象。< / p>

在您的第一个示例中,在第一次调用a->test(1.f)后,a成为“悬空指针”。当您取消引用它以再次调用test时,可以调用未定义的行为。

在第二个示例中,delete this;语句是未定义的行为,因为该对象不是使用new创建的。

答案 1 :(得分:1)

行为未定义,但在典型的现代实现中,访问解除分配的内存的实际“可能性”包括(但不限于):

  1. delete在运行时库级别(RTL)释放内存,但不会将其返回给操作系统。即未启用操作系统级别的内存保护,操作系统继续将内存视为已分配。但是,存储在释放的内存块中的内部RTL数据会破坏您的数据。结果:通过指针访问不会导致代码崩溃,但数据看起来毫无意义(破坏)

  2. 与1相同,但内部RTL数据不会与您的关键数据重叠。代码不会崩溃并继续工作“好像”一切都很“好”。

  3. delete向操作系统释放内存。启用了OS级别的内存保护。任何通过指针访问的尝试都会导致立即崩溃。

  4. 您的示例将按照第二种方案继续进行,即即使您释放内存后,存储在对象中的数据仍然保持不变。

    您在代码中发现的崩溃发生是因为RTL检测到双free次尝试(或尝试free非动态内存,如第二个示例中所示),这除了指出你的问题。