资源透露危险剖析
示例一:
// 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); // 4delete pi;
int ia[10]; // from stack but not heapcout << 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
- 一个字节标记以后内存是否被应用