429 lines
12 KiB
C++
429 lines
12 KiB
C++
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Debug allocator and common STL classes using the allocator.
|
|
// Provides the MSVC heap runtime with the information about the source of allocation:
|
|
// prevents NO_SOURCE_0 for the allocation source for STL classes.
|
|
// USAGE:
|
|
// Include vector, string, set, map
|
|
// Include crtdbg
|
|
// inlcude this file
|
|
// Use cry::vector instead of std::vector,
|
|
// cry::string instead of string,
|
|
// cry::set instead of std::set
|
|
// cry::map instead of std::map
|
|
//
|
|
// In order to specify your own source of allocation, in the constructor specify one or two parameters
|
|
// like:
|
|
// ...
|
|
// cry::map<int,cry::string> m_mapSomething;
|
|
// ...
|
|
// (in the constructor initializer list:)
|
|
// ...
|
|
// m_mapSomething ("My class.mapSomething", 0),
|
|
// ...
|
|
// This works for vector, set and map. For string, specify:
|
|
// cry::string strMyString ("Your string", cry::string::_Allocator("My Source.strMyString", 0));
|
|
//
|
|
// NOTE:
|
|
// You MUST include the map, string, vector and set in order to cry:: classes to be defined here.
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
#ifndef _CRY_DBG_ALLOCATOR_HDR_
|
|
#define _CRY_DBG_ALLOCATOR_HDR_
|
|
#include <string>
|
|
#include <set>
|
|
#include <vector>
|
|
#include <map>
|
|
|
|
#include <iterator>
|
|
#ifdef WIN32
|
|
#include <xmemory>
|
|
#endif
|
|
|
|
#include "TAlloc.h"
|
|
|
|
namespace cry
|
|
{
|
|
#if defined(_DEBUG) && defined(_INC_CRTDBG) && defined(WIN32)
|
|
// This is just a debug mode build allocator. In release mode build it just defaults to the std::allocator
|
|
// The szSource is the actual reason for this class - it will call operator new using this as the source file allocating the block
|
|
// (of course this can be any name). THe number is just because the std lib interface already accepts line number
|
|
// This allocator has static fields, meaning that copying it won't copy the szSource and nSource properties
|
|
|
|
template<class T>
|
|
class dbg_allocator: public TSimpleAllocator<T>
|
|
{ // generic allocator for objects of class T
|
|
public:
|
|
typedef _SIZT size_type;
|
|
typedef _PDFT difference_type;
|
|
typedef T _FARQ *pointer;
|
|
typedef const T _FARQ *const_pointer;
|
|
typedef T _FARQ& reference;
|
|
typedef const T _FARQ& const_reference;
|
|
typedef T value_type;
|
|
|
|
template<class _Other>
|
|
struct rebind
|
|
{ // convert an allocator<T> to an allocator <_Other>
|
|
typedef dbg_allocator<_Other> other;
|
|
};
|
|
|
|
pointer address(reference _Val) const
|
|
{ // return address of mutable _Val
|
|
return (&_Val);
|
|
}
|
|
|
|
const_pointer address(const_reference _Val) const
|
|
{ // return address of nonmutable _Val
|
|
return (&_Val);
|
|
}
|
|
|
|
dbg_allocator<T>(const char* szParentObject = "cry_dbg_alloc", int nParentIndex = 0):
|
|
m_szParentObject(szParentObject),
|
|
m_nParentIndex (nParentIndex)
|
|
{ // construct default allocator (do nothing)
|
|
}
|
|
|
|
dbg_allocator(const dbg_allocator<T>& rThat)
|
|
{ // construct by copying (do nothing)
|
|
m_szParentObject = rThat.m_szParentObject;
|
|
m_nParentIndex = rThat.m_nParentIndex;
|
|
}
|
|
|
|
template<class _Other>
|
|
dbg_allocator(const dbg_allocator<_Other>&rThat)
|
|
|
|
{ // construct from a related allocator (do nothing)
|
|
m_szParentObject = rThat.m_szParentObject;
|
|
m_nParentIndex = rThat.m_nParentIndex;
|
|
}
|
|
|
|
template<class _Other>
|
|
dbg_allocator<T>& operator=(const dbg_allocator<_Other>&rThat)
|
|
{ // assign from a related allocator (do nothing)
|
|
m_szParentObject = rThat.m_szParentObject;
|
|
m_nParentIndex = rThat.m_nParentIndex;
|
|
return (*this);
|
|
}
|
|
|
|
|
|
pointer allocate(size_type _Count, const void *)
|
|
{ // allocate array of _Count elements, ignore hint
|
|
return allocate (_Count);
|
|
}
|
|
|
|
pointer allocate(size_type _Count)
|
|
{ // allocate array of _Count elements
|
|
return (pointer)_malloc_dbg(_Count * sizeof(T), _NORMAL_BLOCK, m_szParentObject, m_nParentIndex);
|
|
}
|
|
|
|
void deallocate(pointer _Ptr, size_type)
|
|
{ // deallocate object at _Ptr, ignore size
|
|
_free_dbg(_Ptr, _NORMAL_BLOCK);
|
|
}
|
|
|
|
void construct(pointer _Ptr, const T& _Val)
|
|
{ // construct object at _Ptr with value _Val
|
|
std::_Construct(_Ptr, _Val);
|
|
}
|
|
|
|
void destroy(pointer _Ptr)
|
|
{ // destroy object at _Ptr
|
|
_Ptr->~T();
|
|
}
|
|
|
|
_SIZT max_size() const
|
|
{ // estimate maximum array size
|
|
_SIZT _Count = (_SIZT)(-1) / sizeof (T);
|
|
return (0 < _Count ? _Count : 1);
|
|
|
|
}
|
|
|
|
// the parent object (on behalf of which to call the new operator)
|
|
const char* m_szParentObject; // the file name
|
|
int m_nParentIndex; // the file line number
|
|
};
|
|
|
|
template<class _Ty,
|
|
class _Other> inline
|
|
bool operator==(const dbg_allocator<_Ty>&rLeft, const dbg_allocator<_Other>&rRight)
|
|
{ // test for allocator equality (always true)
|
|
return rLeft.m_szParentObject == rRight.m_szParentObject && rLeft.m_nParentIndex == rRight.m_nParentIndex;
|
|
}
|
|
|
|
template<class _Ty,
|
|
class _Other> inline
|
|
bool operator!=(const dbg_allocator<_Ty>&, const dbg_allocator<_Other>&)
|
|
{ // test for allocator inequality (always false)
|
|
return rLeft.m_szParentObject != rRight.m_szParentObject && rLeft.m_nParentIndex != rRight.m_nParentIndex;
|
|
}
|
|
|
|
|
|
/*
|
|
template<class T>
|
|
class dbg_allocator: public TSimpleAllocator<T>
|
|
{ // generic allocator for objects of class T
|
|
public:
|
|
dbg_allocator<T>()
|
|
{
|
|
}
|
|
|
|
dbg_allocator<T>(const char* szParentObject, int nParentIndex = 0):
|
|
TSimpleAllocator<T>(szParentObject, nParentIndex)
|
|
{ // construct default allocator (do nothing)
|
|
}
|
|
|
|
dbg_allocator<T>(const dbg_allocator<T>& rThat):
|
|
TSimpleAllocator<T>(rThat)
|
|
{ // construct by copying (do nothing)
|
|
}
|
|
|
|
template<class _Other>
|
|
dbg_allocator(const dbg_allocator<_Other>&rThat):
|
|
TSimpleAllocator<T>(rThat)
|
|
{ // construct from a related allocator (do nothing)
|
|
}
|
|
|
|
template<class _Other>
|
|
dbg_allocator<T>& operator=(const dbg_allocator<_Other>&rThat)
|
|
{ // assign from a related allocator (do nothing)
|
|
*static_cast<TSimpleAllocator<T>*>(this) = rThat;
|
|
return (*this);
|
|
}
|
|
};
|
|
*/
|
|
|
|
template<class T>
|
|
class dbg_struct_allocator: public TSimpleStructAllocator<T>
|
|
{ // generic allocator for objects of class T
|
|
public:
|
|
dbg_struct_allocator<T>()
|
|
{
|
|
}
|
|
|
|
dbg_struct_allocator<T>(const char* szParentObject, int nParentIndex = 0):
|
|
TSimpleStructAllocator<T>(szParentObject, nParentIndex)
|
|
{ // construct default allocator (do nothing)
|
|
}
|
|
|
|
dbg_struct_allocator<T>(const dbg_struct_allocator<T>& rThat):
|
|
TSimpleStructAllocator<T>(rThat)
|
|
{ // construct by copying (do nothing)
|
|
}
|
|
|
|
template<class _Other>
|
|
dbg_struct_allocator(const dbg_struct_allocator<_Other>&rThat):
|
|
TSimpleStructAllocator<T>(rThat)
|
|
{ // construct from a related allocator (do nothing)
|
|
}
|
|
|
|
template<class _Other>
|
|
dbg_struct_allocator<T>& operator=(const dbg_struct_allocator<_Other>&rThat)
|
|
{ // assign from a related allocator (do nothing)
|
|
*static_cast<TSimpleStructAllocator<T>*>(this) = rThat;
|
|
return (*this);
|
|
}
|
|
};
|
|
#else
|
|
template<class T>
|
|
class dbg_allocator: public std::allocator<T>
|
|
{
|
|
public:
|
|
dbg_allocator(const char* szSource = "CryDbgAlloc", int nSource = 0)
|
|
{ // construct default allocator (do nothing)
|
|
}
|
|
|
|
dbg_allocator(const dbg_allocator<T>& rThat):
|
|
std::allocator<T> (rThat)
|
|
{ // construct by copying (do nothing)
|
|
}
|
|
/*
|
|
template<class _Other>
|
|
dbg_allocator(const dbg_allocator<_Other>&rThat):
|
|
std::allocator<T>(rThat)
|
|
{ // construct from a related allocator (do nothing)
|
|
}
|
|
|
|
template<class _Other>
|
|
dbg_allocator<T>& operator=(const dbg_allocator<_Other>&rThat):
|
|
std::allocator<T>(rThat)
|
|
{ // assign from a related allocator (do nothing)
|
|
return (*this);
|
|
}
|
|
|
|
dbg_allocator(const std::allocator<T>& rThat):
|
|
std::allocator<T> (rThat)
|
|
{ // construct by copying (do nothing)
|
|
}
|
|
*/
|
|
template<class _Other>
|
|
dbg_allocator(const std::allocator<_Other>&rThat):
|
|
std::allocator<T>(rThat)
|
|
{ // construct from a related allocator (do nothing)
|
|
}
|
|
|
|
template<class _Other>
|
|
dbg_allocator<T>& operator=(const std::allocator<_Other>&rThat):
|
|
std::allocator<T>(rThat)
|
|
{ // assign from a related allocator (do nothing)
|
|
return (*this);
|
|
}
|
|
};
|
|
#endif
|
|
|
|
#if defined(_DEBUG) && defined(WIN32)
|
|
#if _MSC_VER >= 1300 && defined(_MAP_)
|
|
template <class Key, class Type, class Traits = std::less<Key> >
|
|
class map: public std::map <Key, Type, Traits, dbg_allocator<std::pair<Key, Type> > >
|
|
{
|
|
public:
|
|
typedef dbg_allocator<std::pair<Key, Type> > _Allocator;
|
|
typedef std::map <Key, Type, Traits, _Allocator > _Base;
|
|
map (const char* szParentObject = "STL map", int nParentIndex = 0):
|
|
_Base (_Base::key_compare(), _Base::allocator_type(szParentObject, nParentIndex))
|
|
{
|
|
}
|
|
};
|
|
#endif
|
|
|
|
#if (_MSC_VER >= 1300) && defined(_SET_)
|
|
template <class Key, class Traits = std::less<Key> >
|
|
class set: public std::set <Key, Traits, dbg_allocator<Key> >
|
|
{
|
|
public:
|
|
typedef dbg_allocator<Key> _Allocator;
|
|
typedef std::set <Key, Traits, _Allocator> _Base;
|
|
set (const char* szParentObject = "STL set", int nParentIndex = 0):
|
|
_Base (_Base::key_compare(), _Allocator(szParentObject, nParentIndex))
|
|
{
|
|
}
|
|
};
|
|
#endif
|
|
|
|
#if (_MSC_VER >= 1300) && defined(_VECTOR_)
|
|
template <class Type>
|
|
class vector: public std::vector <Type, dbg_allocator<Type> >
|
|
{
|
|
public:
|
|
typedef dbg_allocator<Type> _Allocator;
|
|
typedef std::vector <Type, _Allocator> _Base;
|
|
typedef vector<Type> _Myt;
|
|
vector (const char* szParentObject = "STL vector", int nParentIndex = 0):
|
|
_Base (_Allocator(szParentObject, nParentIndex))
|
|
{
|
|
}
|
|
vector (const _Myt& that): _Base (that)
|
|
{
|
|
}
|
|
};
|
|
#endif
|
|
|
|
#if (_MSC_VER >= 1300) && defined(_STRING_)
|
|
class string: public std::basic_string<char, std::char_traits<char>, dbg_allocator<char> >
|
|
{
|
|
public:
|
|
typedef dbg_allocator<char> _Allocator;
|
|
typedef std::basic_string<char, std::char_traits<char>, _Allocator> _Base;
|
|
explicit string (const _Allocator allocator = _Allocator("STL string", 0)):
|
|
_Base (allocator)
|
|
{
|
|
}
|
|
string (const char* szThat, const _Allocator allocator = _Allocator("STL string", 0)):
|
|
_Base (szThat, 0, _Base::npos, allocator)
|
|
{
|
|
}
|
|
string (const char* szBegin, const char* szEnd, const _Allocator allocator = _Allocator("STL string", 0)):
|
|
_Base (szBegin, szEnd, allocator)
|
|
{
|
|
}
|
|
string (const _Base& strRight, const _Allocator allocator = _Allocator("STL string", 0)):
|
|
_Base (strRight, 0, npos, allocator)
|
|
{
|
|
}
|
|
};
|
|
#endif
|
|
#else
|
|
//#if _MSC_VER >= 1300 && defined(_MAP_)
|
|
template <class Key, class Type, class Traits = std::less<Key> >
|
|
class map: public std::map <Key, Type, Traits >
|
|
{
|
|
public:
|
|
typedef std::map <Key, Type, Traits> _Base;
|
|
map ()
|
|
{
|
|
}
|
|
map (const char* szParentObject, int nParentIndex = 0)
|
|
{
|
|
}
|
|
};
|
|
//#endif
|
|
|
|
//#if (_MSC_VER >= 1300) && defined(_SET_)
|
|
template <class Key, class Traits = std::less<Key> >
|
|
class set: public std::set <Key, Traits>
|
|
{
|
|
public:
|
|
typedef std::set <Key, Traits> _Base;
|
|
set ()
|
|
{
|
|
}
|
|
set (const char* szParentObject , int nParentIndex = 0)
|
|
{
|
|
}
|
|
};
|
|
//#endif
|
|
|
|
//#if (_MSC_VER >= 1300) && defined(_VECTOR_)
|
|
template <class Type>
|
|
class vector: public std::vector <Type>
|
|
{
|
|
public:
|
|
typedef std::vector <Type> _Base;
|
|
vector ()
|
|
{
|
|
}
|
|
vector (const char* szParentObject, int nParentIndex = 0)
|
|
{
|
|
}
|
|
};
|
|
//#endif
|
|
|
|
//#if (_MSC_VER >= 1300) && defined(_STRING_)
|
|
class string: public string
|
|
{
|
|
public:
|
|
typedef dbg_allocator<char> _Allocator;
|
|
typedef string _Base;
|
|
string ()
|
|
{
|
|
}
|
|
explicit string (const _Allocator allocator)
|
|
{
|
|
}
|
|
string (const char* szThat):
|
|
_Base (szThat)
|
|
{
|
|
}
|
|
string (const char* szThat, const _Allocator allocator):
|
|
_Base (szThat)
|
|
{
|
|
}
|
|
string (const char* szBegin, const char* szEnd):
|
|
_Base (szBegin, szEnd)
|
|
{
|
|
}
|
|
string (const char* szBegin, const char* szEnd, const _Allocator allocator):
|
|
_Base (szBegin, szEnd)
|
|
{
|
|
}
|
|
string (const _Base& strRight):
|
|
_Base (strRight)
|
|
{
|
|
}
|
|
string (const _Base& strRight, const _Allocator allocator):
|
|
_Base (strRight)
|
|
{
|
|
}
|
|
};
|
|
//#endif
|
|
#endif
|
|
}
|
|
#endif |