當前位置:
首頁 > 知識 > C++重載 operator new 和 operator delete 實現內存泄漏跟蹤器

C++重載 operator new 和 operator delete 實現內存泄漏跟蹤器

先來說下實現思路:可以實現一個Trace類,調用 operator new 的時候就將指向分配內存的指針、當前文件、當前行等信息添加進Trace 成員map容器內,在調用operator delete 的時候刪除這些信息。定義一個全局Trace 對象,當程序結束,對象析構時判斷成員map 是否還有信息,如果有則列印出來,表示已經發生內存泄漏,從輸出可以看出是哪一個文件哪一行分配了內存但沒有釋放掉。

DebugNew.h:

C++ Code

1

2

3

4

5

6

7

8

9

#ifndef _DEBUG_NEW_H_

#define _DEBUG_NEW_H_

#ifndef NDEBUG

#include "Tracer.h"

#define new new(__FILE__, __LINE__)

#endif // NDEBUG

#endif // _DEBUG_NEW_H_

Trace.h:

C++ Code

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

#ifndef _TRACER_H_

#define _TRACER_H_

#include <map>

#ifndef NDEBUG

void *operator new(size_t size, const char *file, long line);

void operator delete(void *p);

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

void operator delete[](void *p);

class Tracer

{

private:

class Entry

{

public:

Entry(const char *file = 0, long line = 0)

: file_(file), line_(line) {}

const char *File() const

{

return file_;

}

long Line() const

{

return line_;

}

private:

const char *file_;

long line_;

};

public:

Tracer();

~Tracer();

static bool Ready;

void Add(void *p, const char *file, long line);

void Remove(void *p);

void Dump();

private:

std::map<void *, Entry> mapEntry_;

};

#endif // NDEBUG

#endif // _TRACER_H_

Trace.cpp:

C++ Code

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

#include <iostream>

#include "Tracer.h"

#ifndef NDEBUG

bool Tracer::Ready = false;

Tracer::Tracer()

{

Ready = true;

}

Tracer::~Tracer()

{

Ready = false;

Dump();

}

void Tracer::Add(void *p, const char *file, long line)

{

mapEntry_[p] = Entry(file, line);

}

void Tracer::Remove(void *p)

{

std::map<void *, Entry>::iterator it;

it = mapEntry_.find(p);

if (it != mapEntry_.end())

{

mapEntry_.erase(it);

}

}

void Tracer::Dump()

{

if (mapEntry_.size() > 0)

{

std::cout << "*** Memory leak(s):" << std::endl;

std::map<void *, Entry>::iterator it;

for (it = mapEntry_.begin(); it != mapEntry_.end(); ++it)

{

const char *file = it->second.File();

long line = it->second.Line();

int addr = reinterpret_cast<int>(it->first);

std::cout << "0x" << std::hex << addr << ": "

<< file << ", line " << std::dec << line << std::endl;

}

std::cout << std::endl;

}

}

Tracer NewTrace;

void *operator new(size_t size, const char *file, long line)

{

void *p = malloc(size);

if (Tracer::Ready)

{

NewTrace.Add(p, file, line);

}

return p;

}

void operator delete(void *p)

{

if (Tracer::Ready)

{

NewTrace.Remove(p);

}

free(p);

}

void *operator new[](size_t size, const char *file, long line)

{

void *p = malloc(size);

if (Tracer::Ready)

{

NewTrace.Add(p, file, line);

}

return p;

}

void operator delete[](void *p)

{

if (Tracer::Ready)

{

NewTrace.Remove(p);

}

free(p);

}

#endif // #ifndef NDEBUG

main.cpp:

C++ Code

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

#include <iostream>

using namespace std;

#include "DebugNew.h"

int main(void)

{

int *p = new int;

/*delete p;*/

int *p2 = new int[5];

/*delete[] p2;*/

return 0;

}

C++重載 operator new 和 operator delete 實現內存泄漏跟蹤器

程序 #define new new(__FILE__, __LINE__); 是為了利用__FILE__, 和 __LINE__兩個宏,分別代表文件名和行數。分別重載了

operator new 和 operator new[] 函數以及對應的delete,更詳細的討論可以參見這裡。當全局對象NewTrace 析構時調用Dump成員

函數,如果new 和 delete 沒有匹配,那麼map將存在泄漏信息,並列印出來。

此外只在Debug版本(沒有定義NDEBUG)才跟蹤內存泄漏,所以加上#ifndef NDEBUG ... #endif

而由於一般的C++庫中可能沒有#define new new(__FILE__, __LINE__); 即調用的還是原始的new,但現在程序中並沒有重載這種類

型的new和delete函數,故並不能跟蹤類似map容器之類的內存泄漏,但一般正常使用C++庫容器的話,是不會造成內存泄漏的,

C++庫已經實現得比較完善了,至少比我們自己寫的程序要好很多。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 程序員小新人學習 的精彩文章:

try-catch語句
最詳細的Hadoop環境搭建

TAG:程序員小新人學習 |