【发布时间】:2017-12-12 09:46:03
【问题描述】:
我在我的一个项目中发现了一种奇怪的行为。具体情况如下:
- 我有一个对象。让我们调用
Victim,它包含一个指针变量、一个构造函数和一个析构函数。 - 我有另一个对象,我们调用
Perpetrator,它的构造函数接受Victim对象,并将指针变量复制到里面的具体变量。 - 我创建一个
Victim*,并使用new创建对象,然后通过Perpetrator(*victim)将其提供给Perpetrator。 -
Perpetrator的构造函数完成后,Victim的析构函数被调用并删除对象。
问题是Victim的唯一副本,也就是poor在构建过程中被完全销毁。最后通过delete poor整理程序会导致double-free错误。
该行为在 C++98/11、GCC 4.8.5、7.x 和 LLVM CLANG 中是一致的,因此必须明确定义。这种行为叫什么,它的语义是什么?
我的理论是,由于 constructor 接受一个具体的对象,它被认为是复制的,所以当 constructor / function 完成时它被破坏了。
既然我表扬PoC||GTFO,代码如下:
澄清:示例是有意编写的,因为它是一个更复杂但无泄漏且管理良好的数据结构复杂体的简化模型。删除所有必要的位使它看起来像一个可怕的破代码。在实际代码中,Victim 是长期存在的数据存储,Perpetrator 是用于处理所述数据的临时存储变量。
#include <iostream>
using namespace std;
struct Victim
{
double* pointer;
Victim ()
{
this->pointer = new double(42.2);
}
~Victim ()
{
cout << "Destructor of the Victim is called." << endl;
delete this->pointer;
}
};
struct Perpetrator
{
double concrete;
Perpetrator (Victim victim)
{
concrete = *(victim.pointer);
}
};
int main ()
{
Victim* poor = new Victim();
Perpetrator cruel(*poor);
cout << cruel.concrete << endl;
}
样本输出:
./destructor_test
Destructor of the Victim is called.
42.2
【问题讨论】:
-
0/3/5 规则被打破。
double* pointer;应该只是double value;,所以没有内存管理。 -
示例是故意这样写的。我想证明良性副本可以破坏可能计划使用更长时间的对象。
标签: c++ c++11 constructor