我试图通过重载new
和delete
运算符来编写C ++中的内存跟踪器。但它会循环并一次又一次地调用new
。以下是我的代码。
#ifndef MEMORY_TRACKER_H_
#define MEMORY_TRACKER_H_
#pragma warning( disable : 4290 )
#pragma comment(lib, "Dbghelp.lib")
#include <Windows.h>
#include <malloc.h>
#include <map>
#include <iostream>
#include <DbgHelp.h>
#include <sstream>
#include <vector>
static const int MAX_TRACES = 62;
static const int MAX_LENGTH = 256;
static const int BUFFER_LENGTH = (sizeof(SYMBOL_INFO) + MAX_LENGTH * sizeof(wchar_t) + sizeof(ULONG64) - 1) / sizeof(ULONG64);
static bool SYSTEM_INITIALIZED = false;
typedef struct record_t {
std::string symbol;
std::string address;
std::string filename;
std::string linenumber;
} record;
typedef std::vector<record> record_vec_t;
typedef std::pair<size_t, record_vec_t> record_entry_t;
typedef std::map<size_t, record_entry_t> memory_record_t;
memory_record_t gMemoryRecord;
static record_vec_t GetCallStackDetails(const void* const* trace, int count ) {
record_vec_t callStackVector;
for (int i = 0; i < count; ++i) {
ULONG64 buffer[BUFFER_LENGTH];
DWORD_PTR frame = reinterpret_cast<DWORD_PTR>(trace[i]);
DWORD64 sym_displacement = 0;
PSYMBOL_INFO symbol = reinterpret_cast<PSYMBOL_INFO>(&buffer[0]);
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
symbol->MaxNameLen = MAX_LENGTH;
BOOL has_symbol = SymFromAddr(GetCurrentProcess(), frame, &sym_displacement, symbol);
DWORD line_displacement = 0;
IMAGEHLP_LINE64 line = {};
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
BOOL has_line = SymGetLineFromAddr64(GetCurrentProcess(), frame, &line_displacement, &line);
record curr_rec;
curr_rec.symbol = "(No Symbol)";
std::stringstream formatter;
if (has_symbol) {
curr_rec.symbol = symbol->Name;
formatter.clear();
formatter << " [0x" << trace[i] << "+" << sym_displacement << "]";
curr_rec.address = formatter.str();
} else {
formatter.clear();
formatter << " [0x" << trace[i] << "]";
curr_rec.address = formatter.str();
}
if (has_line) {
formatter.clear();
formatter << line.FileName;
curr_rec.filename = formatter.str();
formatter.clear();
formatter << line.LineNumber;
curr_rec.filename = formatter.str();
}
callStackVector.push_back(curr_rec);
}
return callStackVector;
}
static void addRecord(void *ptr, size_t size) {
if ( SYSTEM_INITIALIZED == false ) {
SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES);
if (SymInitialize(GetCurrentProcess(), NULL, TRUE)) {
SYSTEM_INITIALIZED = true;
} else {
SYSTEM_INITIALIZED = false;
return;
}
}
void* trace[MAX_TRACES];
int count = CaptureStackBackTrace(0, MAX_TRACES , trace, NULL);
record_vec_t record = GetCallStackDetails( trace, count);
record_entry_t entry = std::make_pair( size, record);
gMemoryRecord.insert(std::make_pair((size_t)ptr, entry));
}
static void deleteRecord(void *ptr ) {
memory_record_t::iterator itr = gMemoryRecord.find((size_t)ptr);
if ( itr != gMemoryRecord.end()) {
gMemoryRecord.erase(itr);
}
}
void dumpUnfreedMemory() {
for ( memory_record_t::iterator itr = gMemoryRecord.begin(); itr != gMemoryRecord.end(); ++itr ) {
}
}
// Overloading new operator
void* operator new ( size_t size ) throw ( std::bad_alloc ) {
std::cout << " Overloaded new is called " << std::endl;
void *ptr = (void *)malloc(size);
addRecord(ptr, size);
return ptr;
}
// Overloading delete Operator
void operator delete ( void* ptr ) throw () {
std::cout << " Overloaded delete is called " << std::endl;
deleteRecord(ptr);
free ( ptr );
}
#endif
以下是测试文件
#include "MemoryTracker.h"
int main ( int argc, char **argv) {
int *ptr = new int;
return 0;
}
它将进入GetCallStackDetails
的调用循环,平台为windows
答案 0 :(得分:4)
您正在重载全局operator new
,std::vector<record>
使用默认分配器,它调用operator new
来分配内存。然后调用你的GetCallStack,它分配一个新的向量....
一种解决方案是在向量中使用自定义分配器,该分配器来自单独的内存池,因此它不会调用GetCallStack。