Ich schreibe einen benutzerdefinierten Speichermanager in C++, um "neue" und "löschen" Verwendung zu überwachen.C++ NEU und DELETE Monitor: Überladen NEU und DELETE
In meinem Code habe ich neue, neue Operatoren [], delete, delete [] überladen und verwende eine STL-Map, um die Adressen des zugewiesenen Speichers als Schlüsselwerte zu speichern und die Anzahl der zugewiesenen Bytes als zugeordnete Werte zu speichern . Ich aktualisiere auch byte_counter und number_of_allocations.
Ich halte empfängt den Fehler "Thema 1: EXC_BAD_ACCESS (code = 2, Adresse = 0x7fff5f3fffd8)" (I XCode als meine IDE bin mit), die mich zu diesem Stück Code nimmt:
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;
}
Hier ist mein Code:
#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);
}
Ich bin mir nicht sicher, warum mein Code immer mit BAD_ACCESS Fehler kommt. Wie soll ich meinen Code so gestalten, dass er die STL-Map bei jedem NEW- und DELETE-Einsatz erfolgreich aktualisiert? Bitte helfen und danke!
EDIT: Ich fand, dass der Fehler von meinem überladenen NEW-Operator kommt, der unendlich rekursiv ist. Mein Professor weist darauf hin, dass wir in diesem Codeabschnitt auf void example5() verweisen sollten. Ich bin immer noch nicht sicher, genau das, was ich in meinem Code bin fehlt meine überladene NEW von recursing zu verhindern:
#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;
}
Sie erkennen, dass 'std :: selbst map' verwendet' new'/'delete' selbst intern als Teil des Inhalts der Verwaltung der Karte, die scheinbar Ihre überladenen Operatoren aufruft, oder? –