资源泄漏风险分析

  • 示例一:

    // 1. 唤起 三次构造函数
    // 2. 无法藉由参数进行初始化,因此 Complex 需要有默认构造函数
    Complex *pca = new Complex[3];
    ...
    ...
    // 3. 唤起三次析构函数
    delete[] pca;

    image.png

  • 示例二:

    // 1. 唤起 三次构造函数
    // 2. 无法藉由参数进行初始化,因此 string需要有默认构造函数
    string *psa = new string[3];
    ...
    ...
    // 3. 唤起一次析构函数
    delete psa;

    image.png

  • 问:没对数组里面的每个对象调用析构函数(示例二),会有什么影响呢?

    • 对 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 中的内存布局(后续将详细讲解)
    image.png
class Demo {
public:
    int a;
    omt 
};

image.png

==> (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
    • 一个字节标记当前内存是否被使用

TianSong
737 声望139 粉丝

阿里山神木的种子在3000年前已经埋下,今天不过是看到当年注定的结果,为了未来的自己,今天就埋下一颗好种子吧