我在C++中編寫自定義內存管理器來監視「新建」和「刪除」用法。C++ NEW和DELETE監視器:重載NEW和DELETE
在我的代碼中,我重載了new,new [],delete,delete []運算符,並使用STL映射來保存分配內存的地址作爲鍵值並存儲分配爲映射值的字節數。我也更新byte_counter和number_of_allocations。
我不斷收到錯誤 「主題1:EXC_BAD_ACCESS(代碼= 2,地址= 0x7fff5f3fffd8)」(我使用了Xcode作爲我的IDE),它帶我到這一段代碼:
template <class _Tp, class _Compare, class _Allocator>
template <class ..._Args>
typename __tree<_Tp, _Compare, _Allocator>::__node_holder
__tree<_Tp, _Compare, _Allocator>::__construct_node(_Args&& ...__args)
{
__node_allocator& __na = __node_alloc();
__node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
__node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::forward<_Args>(__args)...);
__h.get_deleter().__value_constructed = true;
return __h;
}
這裏是我的代碼:
#include <iostream>
#include <map>
#include <cstdlib>
using namespace std;
/********************************************************************************/
void* operator new (size_t st);
void* operator new [](size_t st);
void operator delete(void* p);
void operator delete [](void* p);
/********************************************************************************/
class DynamicMemoryManager
{
private:
static int number_of_allocations;
static size_t total_bytes;
static map<const void*, const size_t> mem_map;
public:
DynamicMemoryManager();
static DynamicMemoryManager* create();
static void destroy();
static void print();
static void add(const void* p, const size_t size);
static void remove(const void* p);
};
int DynamicMemoryManager::number_of_allocations = 0;
size_t DynamicMemoryManager::total_bytes = 0;
map<const void*, const size_t> DynamicMemoryManager::mem_map;
DynamicMemoryManager::DynamicMemoryManager() {
number_of_allocations = 0;
total_bytes = 0;
mem_map.clear();
}
void DynamicMemoryManager::print() {
cout << "number_of_allocations: " << number_of_allocations << endl;
cout << "total_bytes: " << total_bytes << endl;
}
void DynamicMemoryManager::add(const void* p, const size_t size) {
number_of_allocations++;
total_bytes += size;
mem_map.insert(pair<const void*, const size_t>(p, size));
}
void DynamicMemoryManager::remove(const void*p) {
size_t sz = mem_map[p];
number_of_allocations--;
total_bytes -= sz;
mem_map.erase(p);
}
/********************************************************************************/
int main()
{
DynamicMemoryManager::print();
int* i = new int(88);
double* d = new double(8.8);
string* s = new string("8888");
char* c = new char('8');
DynamicMemoryManager::print();
delete i;
delete d;
delete s;
delete c;
return 0;
}
/********************************************************************************/
void* operator new (size_t st) {
void* p = malloc(st);
DynamicMemoryManager::add(p, st);
return p;
}
void* operator new [](size_t st) {
void* p = malloc(st);
DynamicMemoryManager::add(p, st);
return p;
}
void operator delete(void* p) {
free(p);
DynamicMemoryManager::remove(p);
}
void operator delete [](void* p) {
free(p);
DynamicMemoryManager::remove(p);
}
我不知道爲什麼我的代碼不斷出現BAD_ACCESS錯誤。我應該如何設計我的代碼,以便它能夠成功更新每個NEW和DELETE使用的STL映射?請幫忙,謝謝!
編輯:我發現錯誤來自我的重載NEW操作無限遞歸。我的教授暗示我們應該在這段代碼中引用void example5()。我真不知道到底是什麼我缺少在我的代碼,以防止過載我來自新遞歸:
#include <array>
#include <map>
#include <functional>
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <regex>
#include <chrono>
#include <ctime>
#include <vector>
#include <memory>
using namespace std::chrono;
using namespace std;
array<string, 12> smonths =
{
"january",
"february",
"march",
"april",
"may",
"june",
"july",
"august",
"september",
"october",
"november",
"december"
};
vector<string> Parse(string text, string split)
{
vector<string> words;
sregex_token_iterator end;
regex pattern(split);
for (sregex_token_iterator pos(text.begin(), text.end(), pattern); pos != end; ++pos)
{
if ((*pos).length() > 0)
{
if ((static_cast<string>(*pos))[0] != 0x20)
words.push_back(*pos);
}
}
return words;
}
int getHash(string s)
{
hash<string> hstring;
return hstring(s);
}
struct KeyValue : pair<string, int>
{
string key;
int value;
KeyValue(string s, int n) { first = s; second = n; }
KeyValue(const KeyValue& kv) { first = kv.first; second = kv.second; }
KeyValue(const KeyValue&& kv) { first = kv.first; second = kv.second; }
};
bool operator == (const KeyValue a, const KeyValue b)
{
return a.first.compare(b.first) == 0;
}
/*
If you think about how you usually allocate memory dynamically
(using the 'new' operator), you could ask why the STL provides
such a thing called allocator that does all the memory management
of the container classes. The concept of allocators was originally
introduced to provide an abstraction for different memory models
to handle the problem of having different pointer types on certain
16-bit operating systems (such as near, far, and so forth).
However, this approach failed. Nowadays, allocators serve as an
abstraction to translate the need to use memory into a raw call
for memory. Allocators simply separate the implementation of
containers, which need to allocate memory dynamically, from the
details of the underlying physical memory management. You can simply
apply different memory models such as shared memory, garbage
collections, and so forth to your containers without any difficulty
because allocators provide a common interface.
*/
template <typename T>
class MallocAllocator
{
public:
typedef T value_type;
MallocAllocator() {}
template <typename U> MallocAllocator(const MallocAllocator<U>& other) {}
T* allocate(size_t count)
{
return (T*)malloc(count * sizeof(T));
}
void deallocate(T* object, size_t n)
{
void* ptr = reinterpret_cast<void*>(object);
free(ptr);
}
};
MallocAllocator<void*> memoryManager;
void* operator new(size_t size)
{
//cout << "Allocating memory..." << endl;
auto newObject = memoryManager.allocate(size);
return newObject;
}
void operator delete(void* objectPtr) noexcept
{
void** ptr = reinterpret_cast<void**>(objectPtr);
memoryManager.deallocate(ptr, 0);
//free(objectPtr);
}
template <typename _Type = void>
struct Less
{ // functor for operator<
constexpr bool operator()(const _Type& _Left, const _Type& _Right) const
{
return (_Left < _Right);
}
};
void example5()
{
int* p = new int;
system_clock::time_point tbegin = system_clock::now();
map<string, int, Less<string>, MallocAllocator<int>> frequency;
ifstream infile("Words.txt");
while (!infile.eof())
{
string buffer;
getline(infile, buffer);
frequency[buffer] = 0;
}
infile.close();
infile.open("Speech.txt");
while (!infile.eof())
{
string buffer;
getline(infile, buffer);
vector<string> vs = Parse(buffer, "[a-zA-Z0-9]*");
for (string s : vs)
{
int& number = frequency[s];
++number;
}
}
ofstream outfile("Frequency.txt");
for (auto p : frequency)
{
if (p.second)
{
outfile << p.first << "\t" << p.second << endl;
cout << p.first << "\t" << p.second << endl;
}
}
outfile.close();
system_clock::time_point tend = system_clock::now();
cout << "Duration: " << static_cast<double>((tend - tbegin).count())/10000000.0 << endl;
}
你知道那'的std :: map'本身使用'new' /'delete'本身內部,爲管理內容的一部分的地圖,似乎調用你的重載操作符,對吧? –