C++NEW和DELETE监视器:重载NEW和DELETE
C++ NEW and DELETE Monitor: Overloaded NEW and DELETE
我正在C++中编写一个自定义内存管理器来监视"new"answers"delete"的使用情况。
在我的代码中,我重载了new、new[]、delete、delete[]运算符,并使用STL映射将已分配内存的地址保存为键值,并将已分配的字节数存储为映射值。我还更新了byte_counter和number_of_allocations。
我一直收到错误"线程1:EXC_BAD_ACCESS(代码=2,地址=0x7fff5f3ffd8)"(我使用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()。我仍然不确定我的代码中到底缺少了什么,以防止过载的NEW再次出现:
#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;
}
我应该如何设计我的代码,以便它在每次使用NEW和DELETE时成功地更新STL映射?
不容易。CCD_ 1分配和释放动态存储器的方法,以存储和丢弃地图的元素。
它们使用Allocator
的相应成员函数来分配和解除分配动态内存。默认情况下Allocator
是std::allocator<std::pair<const Key, T>>
std::allocator
通过调用全局operator new
并通过调用全局operator delete
(即要替换为受监控版本的操作符,这些操作符插入和删除元素您的std::map
)。
因此,例如,当您的operator new
开始在中插入第一个元素时映射,在插入操作中再次调用它,该操作将启动另一次插入操作等等,直到内存耗尽并崩溃(正如您所看到的)。
避免这种情况的唯一方法是将地图设为CCD_ 10,其中std::map<Key,T,Compare,Allocator>
1是您自己编写的用于分配和解除分配的分配器动态存储器而不调用CCD_ 12或CCD_。
您可以尝试使用标准C库的malloc
和free
。
但我劝你不要麻烦。如果你认为你的内存管理器会揭示堆的所有信息,你必须用什么方式来写就足够了向你表明它不会。它对自己的堆使用情况一无所知,也不了解通过处理堆的程序中链接的任何其他内容的堆使用情况CCD_ 16接口。看看堆会发生什么,解决方案是Valgrind对于OS X,请参阅Yosemite和Valgrind
- g++用户定义的动态链接库上的全局new和delete运算符
- 体系结构x86_64的未定义符号:std:terminate(),typeinfo,运算符delete[],运算符new
- 为什么 std::vector 使用 std::分配器而不是运算符 new 和 delete?
- 重载 new 和 delete 会导致 valgrind 错误
- 基类指针:在哪里使用 new 和 delete
- C++:为什么可以在没有事先使用 new 的情况下在指向结构的指针上使用 delete?
- 重载运算符 new 和运算符 delete 带有三个参数
- 如果我为一个类编写new和delete运算符,我是否必须编写它们的所有重载
- new[] / delete[] 并在C++中抛出构造函数/析构函数
- QQuickView new-delete-type-mismatch
- 使用重载的 new 和 delete 运算符跟踪已用内存
- 创建 myNew/myDelete 以替换 new/new[]/delete/delete[]
- 为多线程环境包装 c++ new/delete 的安全/好方法
- C++ VS:多 DLL 解决方案中的'new'和'delete'覆盖
- 如何使用 new 和 delete 与 OpenGL 的缓冲区对象一起使用?
- c++ 运算符 new[]/delete [] 是否调用运算符 new/delete?
- 继承类上的运算符new和delete.操作员删除未执行
- 在不同的编译器版本中调用new[]和delete[]
- `delete []`on`int*````new'''给出了malloc错误
- C++内存分配失败(使用 new & delete)