C++:删除这个; return x;
C++: delete this; return x;
嘿,我对某些 C++ 行为很好奇,因为如果此行为是一致的,那么我正在处理的代码在简单性方面将从中受益匪浅。基本上,我的想法是让我的对象 A
中的特定函数计算返回 float
的复杂计算,但就在返回 float
之前,偶尔会调用 delete this
.
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)
注意请不要用一长串的解释来说明为什么这是不好的coding/etiquette或其他什么,不在乎,我只是对可能性感兴趣。
成员函数调用 delete this;
是安全的 如果 您知道该对象是使用标量 new
分配的,并且其他任何东西都不会使用之后的对象。
在您的第一个示例中,在第一次调用 a->test(1.f)
后,a
变为 "dangling pointer"。当您取消引用它以第二次调用 test
时,您调用了未定义的行为。
在您的第二个示例中,delete this;
语句是未定义行为,因为对象不是使用 new
创建的。
行为未定义,但在典型的现代实现中,访问释放内存的实用 "possibilities" 包括(但不限于):
delete
在 运行 时间库级别 (RTL) 释放内存,但不会 return 到 OS。 IE。 OS 级内存保护未启用,OS 继续看到已分配的内存。但是,存储在已释放内存块中的内部 RTL 数据会破坏您的数据。结果:通过指针访问不会导致您的代码崩溃,但数据看起来毫无意义(被破坏)
与 1 相同,但内部 RTL 数据恰好不会与您的关键数据重叠。代码不会崩溃并继续工作 "as if" 一切都是 "fine"。
delete
释放内存给 OS。 OS 级内存保护已启用。任何通过指针访问的尝试都会导致立即崩溃。
您的示例按照第二种情况进行,即存储在对象中的数据似乎在您释放内存后仍保持不变。
您在代码中观察到的崩溃发生是因为 RTL 检测到两次 free
尝试(或尝试 free
非动态内存,如第二个示例),这有点除了您问题的上下文中的要点。
嘿,我对某些 C++ 行为很好奇,因为如果此行为是一致的,那么我正在处理的代码在简单性方面将从中受益匪浅。基本上,我的想法是让我的对象 A
中的特定函数计算返回 float
的复杂计算,但就在返回 float
之前,偶尔会调用 delete this
.
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)
注意请不要用一长串的解释来说明为什么这是不好的coding/etiquette或其他什么,不在乎,我只是对可能性感兴趣。
成员函数调用 delete this;
是安全的 如果 您知道该对象是使用标量 new
分配的,并且其他任何东西都不会使用之后的对象。
在您的第一个示例中,在第一次调用 a->test(1.f)
后,a
变为 "dangling pointer"。当您取消引用它以第二次调用 test
时,您调用了未定义的行为。
在您的第二个示例中,delete this;
语句是未定义行为,因为对象不是使用 new
创建的。
行为未定义,但在典型的现代实现中,访问释放内存的实用 "possibilities" 包括(但不限于):
delete
在 运行 时间库级别 (RTL) 释放内存,但不会 return 到 OS。 IE。 OS 级内存保护未启用,OS 继续看到已分配的内存。但是,存储在已释放内存块中的内部 RTL 数据会破坏您的数据。结果:通过指针访问不会导致您的代码崩溃,但数据看起来毫无意义(被破坏)与 1 相同,但内部 RTL 数据恰好不会与您的关键数据重叠。代码不会崩溃并继续工作 "as if" 一切都是 "fine"。
delete
释放内存给 OS。 OS 级内存保护已启用。任何通过指针访问的尝试都会导致立即崩溃。
您的示例按照第二种情况进行,即存储在对象中的数据似乎在您释放内存后仍保持不变。
您在代码中观察到的崩溃发生是因为 RTL 检测到两次 free
尝试(或尝试 free
非动态内存,如第二个示例),这有点除了您问题的上下文中的要点。