📄 object.h
字号:
stream.
*/
static unsigned GetLevel();
/** Determine if the level may cause trace output.
This checks against the current global trace level set by #PSetTraceLevel#
for if the trace output may be emitted. This is used by the PTRACE macro.
*/
static BOOL CanTrace(unsigned level /** Trace level to check */);
/** Set the stream to be used for trace output.
This stream is used for all trace output using the various trace functions
and macros.
*/
static void SetStream(ostream * out /** New output stream from trace. */ );
/** Begin a trace output.
If the trace stream output is used outside of the provided macros, it
should be noted that a mutex is obtained on the call to #PBeginTrace# which
will prevent any other threads from using the trace stream until the
#PEndTrace# function is called.
So a typical usage would be:
\begin{verbatim}
ostream & s = PTrace::Begin(3, __FILE__, __LINE__);
s << "hello";
if (want_there)
s << " there";
s << '!' << PTrace::End();
\end{verbatim}
*/
static ostream & Begin(
unsigned level, ///< Log level for output
const char * fileName, ///< Filename of source file being traced
int lineNum ///< Line number of source file being traced.
);
/** End a trace output.
If the trace stream output is used outside of the provided macros, the
#PEndTrace# function must be used at the end of the section of trace
output. A mutex is obtained on the call to #PBeginTrace# which will prevent
any other threads from using the trace stream until the PEndTrace. The
#PEndTrace# is used in a similar manner to #::endl# or #::flush#.
So a typical usage would be:
\begin{verbatim}
ostream & s = PTrace::Begin();
s << "hello";
if (want_there)
s << " there";
s << '!' << PTrace::End();
\end{verbatim}
*/
static ostream & End(ostream & strm /** Trace output stream being completed */);
/** Class to trace Execution blocks.
This class is used for tracing the entry and exit of program blocks. Upon
construction it outputs an entry trace message and on destruction outputs an
exit trace message. This is normally only used from in the PTRACE_BLOCK macro.
*/
class Block {
public:
/** Output entry trace message. */
Block(
const char * fileName, ///< Filename of source file being traced
int lineNum, ///< Line number of source file being traced.
const char * traceName
///< String to be output with trace, typically it is the function name.
);
/// Output exit trace message.
~Block();
private:
const char * file;
int line;
const char * name;
};
};
#if !PTRACING
#define PTRACE_PARAM(param)
#define PTRACE_BLOCK(n)
#define PTRACE_LINE()
#define PTRACE(level, arg)
#define PTRACE_IF(level, cond, args)
#else
/* Macro to conditionally declare a parameter to a function to avoid compiler
warning due that parameter only being used in a PTRACE */
#define PTRACE_PARAM(param) param
/** Trace an execution block.
This macro creates a trace variable for tracking the entry and exit of program
blocks. It creates an instance of the PTraceBlock class that will output a
trace message at the line PTRACE_BLOCK is called and then on exit from the
scope it is defined in.
*/
#define PTRACE_BLOCK(name) PTrace::Block __trace_block_instance(__FILE__, __LINE__, name)
/** Trace the execution of a line.
This macro outputs a trace of a source file line execution.
*/
#define PTRACE_LINE() \
if (!PTrace::CanTrace(1)) ; else \
PTrace::Begin(1, __FILE__, __LINE__) << __FILE__ << '(' << __LINE__ << ')' << PTrace::End
/** Output trace.
This macro outputs a trace of any information needed, using standard stream
output operators. The output is only made if the trace level set by the
#PSetTraceLevel# function is greater than or equal to the #level# argument.
*/
#define PTRACE(level, args) \
if (!PTrace::CanTrace(level)) ; else \
PTrace::Begin(level, __FILE__, __LINE__) << args << PTrace::End
/** Output trace on condition.
This macro outputs a trace of any information needed, using standard stream
output operators. The output is only made if the trace level set by the
#PSetTraceLevel# function is greater than or equal to the #level# argument
and the conditional is TRUE. Note the conditional is only evaluated if the
trace level is sufficient.
*/
#define PTRACE_IF(level, cond, args) \
if (!(PTrace::CanTrace(level) && (cond))) ; else \
PTrace::Begin(level, __FILE__, __LINE__) << args << PTrace::End
#endif
#if PMEMORY_CHECK
/** Memory heap checking class.
This class implements the memory heap checking and validation functions. It
maintains lists of allocated block so that memory leaks can be detected. It
also initialises memory on allocation and deallocation to help catch errors
involving the use of dangling pointers.
*/
class PMemoryHeap {
protected:
/// Initialise the memory checking subsystem.
PMemoryHeap();
public:
// Clear up the memory checking subsystem, dumping memory leaks.
~PMemoryHeap();
/** Allocate a memory block.
This allocates a new memory block and keeps track of it. The memory
block is filled with the value in the #allocFillChar# member variable
to help detect uninitialised structures.
@return pointer to newly allocated memory block.
*/
static void * Allocate(
size_t nSize, ///< Number of bytes to allocate.
const char * file, ///< Source file name for allocating function.
int line, ///< Source file line for allocating function.
const char * className ///< Class name for allocating function.
);
/** Allocate a memory block.
This allocates a new memory block and keeps track of it. The memory
block is filled with the value in the #allocFillChar# member variable
to help detect uninitialised structures.
@return pointer to newly allocated memory block.
*/
static void * Allocate(
size_t count, ///< Number of items to allocate.
size_t iSize, ///< Size in bytes of each item.
const char * file, ///< Source file name for allocating function.
int line ///< Source file line for allocating function.
);
/** Change the size of an allocated memory block.
This allocates a new memory block and keeps track of it. The memory
block is filled with the value in the #allocFillChar# member variable
to help detect uninitialised structures.
@return pointer to reallocated memory block. Note this may
{\em not} be the same as the pointer passed into the function.
*/
static void * Reallocate(
void * ptr, ///< Pointer to memory block to reallocate.
size_t nSize, ///< New number of bytes to allocate.
const char * file, ///< Source file name for allocating function.
int line ///< Source file line for allocating function.
);
/** Free a memory block.
The memory is deallocated, a warning is displayed if it was never
allocated. The block of memory is filled with the value in the
#freeFillChar# member variable.
*/
static void Deallocate(
void * ptr, ///< Pointer to memory block to deallocate.
const char * className ///< Class name for deallocating function.
);
/** Validation result.
*/
enum Validation {
Ok, Bad, Trashed
};
/** Validate the memory pointer.
The #ptr# parameter is validated as a currently allocated heap
variable.
@return Ok for pointer is in heap, Bad for pointer is not in the heap
or Trashed if the pointer is in the heap but has overwritten the guard
bytes before or after the actual data part of the memory block.
*/
static Validation Validate(
void * ptr, ///< Pointer to memory block to check
const char * className, ///< Class name it should be.
ostream * error ///< Stream to receive error message (may be NULL)
);
/** Validate all objects in memory.
This effectively calls Validate() on every object in the heap.
@return TRUE if every object in heap is Ok.
*/
static BOOL ValidateHeap(
ostream * error = NULL ///< Stream to output, use default if NULL
);
/** Ignore/Monitor allocations.
Set internal flag so that allocations are not included in the memory
leak check on program termination.
Returns the previous state.
*/
static BOOL SetIgnoreAllocations(
BOOL ignore ///< New flag for allocation ignoring.
);
/** Get memory check system statistics.
Dump statistics output to the default stream.
*/
static void DumpStatistics();
/** Get memory check system statistics.
Dump statistics output to the specified stream.
*/
static void DumpStatistics(ostream & strm /** Stream to output to */);
/* Get number of allocation.
Each allocation is counted and if desired the next allocation request
number may be obtained via this function.
@return Allocation request number.
*/
static DWORD GetAllocationRequest();
/** Dump allocated objects.
Dump ojects allocated and not deallocated since the specified object
number. This would be a value returned by the #GetAllocationRequest()#
function.
Output is to the default stream.
*/
static void DumpObjectsSince(
DWORD objectNumber ///< Memory object to begin dump from.
);
/** Dump allocated objects.
Dump ojects allocated and not deallocated since the specified object
number. This would be a value returned by the #GetAllocationRequest()#
function.
*/
static void DumpObjectsSince(
DWORD objectNumber, ///< Memory object to begin dump from.
ostream & strm ///< Stream to output dump
);
/** Set break point allocation number.
Set the allocation request number to cause an assert. This allows a
developer to cause a halt in a debugger on a certain allocation allowing
them to determine memory leaks allocation point.
*/
static void SetAllocationBreakpoint(
DWORD point ///< Allocation number to stop at.
);
protected:
void * InternalAllocate(
size_t nSize, // Number of bytes to allocate.
const char * file, // Source file name for allocating function.
int line, // Source file line for allocating function.
const char * className // Class name for allocating function.
);
Validation InternalValidate(
void * ptr, // Pointer to memory block to check
const char * className, // Class name it should be.
ostream * error // Stream to receive error message (may be NULL)
);
void InternalDumpStatistics(ostream & strm);
void InternalDumpObjectsSince(DWORD objectNumber, ostream & strm);
class Wrapper {
public:
Wrapper();
~Wrapper();
PMemoryHeap * operator->() const { return instance; }
private:
PMemoryHeap * instance;
};
friend class Wrapper;
enum Flags {
NoLeakPrint = 1
};
#pragma pack(1)
struct Header {
enum {
// Assure that the Header struct is aligned to 8 byte boundary
NumGuardBytes = 16 - (sizeof(Header *) +
sizeof(Header *) +
sizeof(const char *) +
sizeof(const char *) +
sizeof(size_t) +
sizeof(DWORD) +
sizeof(WORD) +
sizeof(BYTE))%8
};
Header * prev;
Header * next;
const char * className;
const char * fileName;
size_t size;
DWORD request;
WORD line;
BYTE flags;
char guard[NumGuardBytes];
static char GuardBytes[NumGuardBytes];
};
#pragma pack()
BOOL isDestroyed;
Header * listHead;
Header * listTail;
static DWORD allocationBreakpoint;
DWORD allocationRequest;
DWORD firstRealObject;
BYTE flags;
char allocFillChar;
char freeFillChar;
DWORD currentMemoryUsage;
DWORD peakMemoryUsage;
DWORD currentObjects;
DWORD peakObjects;
DWORD totalObjects;
ostream * leakDumpStream;
#if defined(_WIN32)
CRITICAL_SECTION mutex;
#elif defined(P_PTHREADS)
pthread_mutex_t mutex;
#elif defined(P_VXWORKS)
void * mutex;
#endif
};
/** Allocate memory for the run time library.
This version of free is used for data that is not to be allocated using the
memory check system, ie will be free'ed inside the C run time library.
*/
inline void * runtime_malloc(size_t bytes /** Size of block to allocate */ ) { return malloc(bytes); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -