资源透露危险剖析
-
示例一:
// 1. 唤起 三次构造函数 // 2. 无奈藉由参数进行初始化,因而 Complex 须要有默认构造函数 Complex *pca = new Complex[3]; ... ... // 3. 唤起三次析构函数 delete[] pca;
-
示例二:
// 1. 唤起 三次构造函数 // 2. 无奈藉由参数进行初始化,因而 string 须要有默认构造函数 string *psa = new string[3]; ... ... // 3. 唤起一次析构函数 delete psa;
-
问:没对数组外面的每个对象调用析构函数(示例二),会有什么影响呢?
- 对 class without pointer 可能没有影响(不会有资源泄露)
- 对 class with pointer 通常有影响(会有资源泄露)
-
阐明:
- 示例一中,当
delete pca;
pca 指向的全副内存空间将会被平安开释 - 示例二中,当
delete psa;
psa 指向的全副内存空间将会被平安开释,但因为 string 实现中蕴含指针指向一段堆空间中申请的内存空间以存储字符串,而数组元素数量的析构函数未被全副对应调用,导致字符串空间未被开释,因而会造成资源泄露
- 示例一中,当
-
总结
- new, delete ; new [], delete [] 须要配对应用
数组元素的结构与析构程序
#include <iostream>
using namespace std;
class A
{
public:
int id;
A() : id(0) {cout << "default ctor.this=" << this << "id=" << id << endl;}
A(int i) : id(i) {cout << "default ctor.this=" << this << "id=" << id << endl;}
~A() {cout << "dtor.this=" << this << "id=" << id << endl;}
};
constexpr size_t size = 3;
int main()
{
// A 必须有默认构造函数
// 默认结构函数调用三次,[0] 先于 [1] 先于 [2]
A *buf = new A[size];
A* tmp = buf;
cout << "buf=" << buf << "tmp=" << tmp << endl;
for (size_t i=0; i < size; ++i) {
// placement new:在指定的地址结构对象
new (tmp++)A(i);
}
cout << "buf=" << buf << "tmp=" << tmp << endl;
// 析构函数三次被调用(秩序逆反,[2] 先于 [1] 先于 [0])delete[] buf;
return 0;
}
-
总结
- 数组中元素的结构程序与析构程序相同
在内存块中的数组大小
(array size, in memory block)
int *pi = new int[10];// from heap but not stack
cout << sizeof(pi); // 4
delete pi;
int ia[10]; // from stack but not heap
cout << sizeof(ia); // 40
- vc6 中的内存布局(后续将具体解说)
class Demo {
public:
int a;
omt
};
==> (32 + 4) + 4 + 36 + (4 * 2) = 84
==> 84 + 12 = 96 = 60H
==> 60H + 1H = 61H
-
阐明 [后续将具体解说]
- 84 bytes:
- 32byte : Debugger Header
- 4 byte : no man land
- 4 byte : 对应图中 3,标记数组元素数量
- 36byte : Demo object
-
4 * 2 byte : up cookie + down cookie
- 60H bytes
-
16 字节对齐
- 61H bytes
- 一个字节标记以后内存是否被应用