[英]Memory Allocation by STL C++ Objects
我使用malloc_stats()函數來顯示進程使用的“系統字節”和“使用中”字節的數量。 我想知道使用中的字節是否還包括STL C ++對象使用的內存,如map,vector,sets?
如果是,是否可以安全地假設這只是進程將使用的內存量?
這沒有在標准中指定,new可能會調用malloc。 在我使用過的實現中,確實如此。
做你想做的事情的最好方法是定義你自己的新運算符來計算分配的內存,或者像STL容器一樣使用會計分配器:
#include <memory>
#include <limits>
extern size_t allocated;
template <class T>
class accounting_allocator {
public:
// type definitions
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
//static size_t allocated;
// rebind allocator to type U
template <class U>
struct rebind {
typedef accounting_allocator<U> other;
};
// return address of values
pointer address (reference value) const {
return &value;
}
const_pointer address (const_reference value) const {
return &value;
}
/* constructors and destructor
* - nothing to do because the allocator has no state
*/
accounting_allocator() throw() {
}
accounting_allocator(const accounting_allocator&) throw() {
}
template <class U>
accounting_allocator (const accounting_allocator<U>&) throw() {
}
~accounting_allocator() throw() {
}
// return maximum number of elements that can be allocated
size_type max_size () const throw() {
// std::cout << "max_size()" << std::endl;
return std::numeric_limits<std::size_t>::max() / sizeof(T);
}
// allocate but don't initialize num elements of type T
pointer allocate (size_type num, const void* = 0) {
// print message and allocate memory with global new
//std::cerr << "allocate " << num << " element(s)" << " of size " << sizeof(T) << std::endl;
pointer ret = (pointer)(::operator new(num*sizeof(T)));
//std::cerr << " allocated at: " << (void*)ret << std::endl;
allocated += num * sizeof(T);
//std::cerr << "allocated: " << allocated/(1024*1024) << " MB" << endl;
return ret;
}
// initialize elements of allocated storage p with value value
void construct (pointer p, const T& value) {
// initialize memory with placement new
new((void*)p)T(value);
}
// destroy elements of initialized storage p
void destroy (pointer p) {
// destroy objects by calling their destructor
p->~T();
}
// deallocate storage p of deleted elements
void deallocate (pointer p, size_type num) {
// print message and deallocate memory with global delete
#if 0
std::cerr << "deallocate " << num << " element(s)"
<< " of size " << sizeof(T)
<< " at: " << (void*)p << std::endl;
#endif
::operator delete((void*)p);
allocated -= num * sizeof(T);
}
};
#if 0
template<>
class accounting_allocator<void>
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef void* pointer;
typedef const void* const_pointer;
typedef void value_type;
template<typename _Tp1>
struct rebind { typedef allocator<_Tp1> other; };
};
#endif
// return that all specializations of this allocator are interchangeable
template <class T1, class T2>
bool operator== (const accounting_allocator<T1>&,
const accounting_allocator<T2>&) throw() {
return true;
}
template <class T1, class T2>
bool operator!= (const accounting_allocator<T1>&,
const accounting_allocator<T2>&) throw() {
return false;
}
/************** accounting allocator end ***********/
使用new進行記帳的一個例子:雖然我更喜歡使用(3)malloc_hook和unordered_map
size_t used_mem = 0;
std::map<void*,size_t> acc;
void* operator new(size_t size) throw (std::bad_alloc)
{
void *mem;
if(size == 0)
size = 1;
mem = malloc(size);
if(mem) {
memset(mem, 0, size);
used_mem += size;
acc[mem] = size;
return mem;
}
std::new_handler nh = std::set_new_handler(0);
std::set_new_handler(nh);
if (nh) {
(*nh)();
return (void*)0;
} else {
//return (void*)0;
throw std::bad_alloc();
}
}
void operator delete(void *mem) throw()
{
std::map<void*,size_t>::iterator i = acc.find(mem);
if( i != acc.end() ) {
size_t size = i->second;
used_mem -= size;
}
free(mem);
}
我的系統上沒有malloc_stats函數,但你可以通過創建一個1000000 int
s的向量來運行一個簡單的測試(只是確保你保存所有的工作,以防萬一你不小心耗盡所有的RAM並崩潰你的系統 :-) )。
請注意,在許多操作系統上, malloc
不是為程序分配內存的唯一方法。 例如,在Linux上,您(或C ++實現)可以跳過malloc()
並使用較低級別的系統函數,如mmap()
和sbrk()
。 因此, malloc_stats
可能不會告訴您程序正在使用的所有內存。 檢查getrusage
為此。
你不能總是假設默認的分配器和operator new
使用malloc
,但很可能所有都來自同一個池。 您詢問特定於Linux的函數這一事實使其成為這一特定上下文的安全假設。
其他人建議您定義自定義分配器類。 只有在每個STL容器聲明中將該分配器作為模板參數傳遞時,這才有效。 這是相當容易出錯的,因此我不建議將其作為簡單的分析策略。
至於第二個問題,不,除了STL容器之外的其他東西將分配內存。 例如, fstream
以實現定義的方式創建I / O緩沖區。 algorithm
某些函數會創建temporary_buffer
對象,而不使用分配器。 ( temporary_buffer
不是標准的一部分;它是原始HP / SGI STL的一部分。其他實現可能稱之為其他實現,但在任何情況下都允許某些函數分配臨時工作空間。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.