Interview_C++_day26

通过重载 \(new/delete\) 来检测内存泄漏的简易实现

讲每次 \(new\) 产生的内存记录,并在 \(delete\) 的时候删去记录,那么最后剩下的就是发生内存泄漏的代码。

#include <bits/stdc++.h>
using namespace std;

class TraceNew {
public:
    class TraceInfo {
    private:
        const char* file;
        size_t line;
    public:
        TraceInfo();
        TraceInfo(const char *File, size_t Line);
        ~TraceInfo();
        const char* File() const;
        size_t Line();
    };
    TraceNew();
    ~TraceNew();
    void Add(void*, const char*, size_t);
    void Remove(void*);
    void Dump();
private:
    map<void*, TraceInfo> mp;
} trace;

TraceNew::TraceInfo::TraceInfo() {
}

TraceNew::TraceInfo::TraceInfo(const char *File, size_t Line) : file(File), line(Line) {
}

TraceNew::TraceInfo::~TraceInfo() {
    delete file;
}

const char* TraceNew::TraceInfo::File() const {
    return file;
}

size_t TraceNew::TraceInfo::Line() {
    return line;
}

TraceNew::TraceNew() {
    mp.clear();
}

TraceNew::~TraceNew() {
    Dump();
    mp.clear();
}

void TraceNew::Add(void *p, const char *file, size_t line) {
    mp[p] = TraceInfo(file, line);
}

void TraceNew::Remove(void *p) {
    auto it = mp.find(p);
    if(it != mp.end())  mp.erase(it);
}

void TraceNew::Dump() {
    for(auto it : mp) {
        cout << it.first << " " << "memory leak on file: " << it.second.File() << " line: " << it.second.Line() << endl;
    }
}

void* operator new(size_t size, const char *file, size_t line) {
    void* p = malloc(size);
    trace.Add(p, file, line);
    return p;
}

void* operator new[](size_t size, const char *file, size_t line) {
    return operator new(size, file, line);
}

void operator delete(void *p) {
    trace.Remove(p);
    free(p);
}

void operator delete[](void *p) {
    operator delete(p); 
}

#define new new(__FILE__,__LINE__)

int main() {
    int *p = new int;
    int *q = new int[10];
    return 0;
}

/*
0xa71850 memory leak on file: a.cpp line: 90
0xa719b8 memory leak on file: a.cpp line: 91
*/

垃圾回收机制

之前使用过,但现在不再使用或者没有任何指针再指向的内存空间就称为 "垃圾"。而将这些 "垃圾" 收集起来以便再次利用的机制,就被称为“垃圾回收”。

垃圾回收机制可以分为两大类:

  1. 基于引用计数的垃圾回收器
    • 系统记录对象被引用的次数。当对象被引用的次数变为 \(0\) 时,该对象即可被视作 "垃圾" 而回收。但难以处理循环引用的情况。
  2. 基于跟踪处理的垃圾回收器
    • 标记-清除:对所有存活对象进行一次全局遍历来确定哪些对象可以回收。从根出发遍历一遍找到所有可达对象(活对象),其它不可达的对象就是垃圾对象,可被回收。
    • 标记-缩并:直接清除对象会造成大量的内存碎片,所以调整所有活的对象缩并到一起,所有垃圾缩并到一起,然后一次清除。
    • 标记-拷贝:堆空间分为两个部分 \(From\)\(To\)。刚开始系统只从 \(From\) 的堆空间里面分配内存,当 \(From\) 分配满的时候系统就开始垃圾回收:从\(From\) 堆空间找出所有的活对象,拷贝到 \(To\) 的堆空间里。这样一来,\(From\) 的堆空间里面就全剩下垃圾了。而对象被拷贝到 \(To\) 里之后,在 \(To\) 里是紧凑排列的。接下来是需要将 \(From\)\(To\) 交换一下角色,接着从新的 \(From\) 里面开始分配。

原文链接: https://www.cnblogs.com/Jiaaaaaaaqi/p/12513072.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    Interview_C++_day26

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/335813

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月1日 下午10:19
下一篇 2023年3月1日 下午10:19

相关推荐