mmgr.h: slightly better comments / spacing
wdbg: fixed root cause of assert noted during 2005-02-05 meeting (now skip UDT child symbols that don't have an offset, i.e. uninteresting stuff like BaseClass symbols) This was SVN commit r1915.
This commit is contained in:
parent
ce27068bac
commit
614e523c89
@ -32,38 +32,39 @@
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
//
|
||||
// optional additional checks, enabled via mmgr_set_options.
|
||||
// these slow down the application; see 'digging deeper' above.
|
||||
// these slow down the application; see 'digging deeper' in documentation.
|
||||
//
|
||||
|
||||
// log all allocation/deallocation operations undertaken.
|
||||
const uint MMGR_LOG_ALL = 0x01;
|
||||
const uint MMGR_LOG_ALL = 0x001;
|
||||
|
||||
// validate all allocations on every memory API call. slow!
|
||||
const uint MMGR_VALIDATE_ALL = 0x02;
|
||||
const uint MMGR_VALIDATE_ALL = 0x002;
|
||||
|
||||
// fill the user-visible part of each allocation with a certain pattern
|
||||
// on alloc and free. this is required for unused memory tracking.
|
||||
const uint MMGR_FILL = 0x04;
|
||||
const uint MMGR_FILL = 0x004;
|
||||
|
||||
// log all enter/exit into our main functions. if there's an
|
||||
// log all enter/exit into our API. if there's an
|
||||
// unmatched pair in the log, we know where a crash occurred.
|
||||
const uint MMGR_TRACE = 0x08;
|
||||
const uint MMGR_TRACE = 0x008;
|
||||
|
||||
// when calling global operator delete, where we can't pass owner
|
||||
// information via macro, find out who called us via stack trace
|
||||
// and resolve the symbol via debug information.
|
||||
// more informative, but adds 500µs to every call.
|
||||
const uint MMGR_RESOLVE_OWNER = 0x10;
|
||||
// use debug information to resolve owner address to file/line/function.
|
||||
// note: passing owner information to global operator delete via macro
|
||||
// isn't reliable, so a stack backtrace (list of function addresses) is all
|
||||
// we have there. this costs ~500µs per unique call site on Windows.
|
||||
const uint MMGR_RESOLVE_OWNER = 0x010;
|
||||
|
||||
// force each log line to be written directly to disk. slow!
|
||||
// use only when the application is crashing, to make sure all
|
||||
// available information is written out.
|
||||
const uint MMGR_FLUSH_LOG = 0x20;
|
||||
const uint MMGR_FLUSH_LOG = 0x020;
|
||||
|
||||
// an alias that includes all of the above.
|
||||
const uint MMGR_ALL = 0xff;
|
||||
// an alias that includes all of the above. (more convenient)
|
||||
const uint MMGR_ALL = 0xfff;
|
||||
|
||||
// return the current options unchanged.
|
||||
const uint MMGR_QUERY = ~0;
|
||||
@ -76,7 +77,7 @@ extern void mmgr_break_on_alloc(uint count);
|
||||
extern void mmgr_break_on_realloc(const void*);
|
||||
extern void mmgr_break_on_free(const void*);
|
||||
|
||||
// "proactive" validation: (see 'digging deeper' above)
|
||||
// "proactive" validation: (see 'digging deeper')
|
||||
extern bool mmgr_is_valid_ptr(const void*);
|
||||
extern bool mmgr_are_all_valid(void);
|
||||
|
||||
@ -84,21 +85,22 @@ extern bool mmgr_are_all_valid(void);
|
||||
extern void mmgr_write_report(void);
|
||||
extern void mmgr_write_leak_report(void);
|
||||
|
||||
|
||||
//
|
||||
// our wrappers for C++ memory handling functions
|
||||
//
|
||||
|
||||
// note that all line numbers are int, for compatibility with external
|
||||
// overloaded operator new.
|
||||
// note that all line numbers are int, for compatibility with any external
|
||||
// overloaded operator new (in case someone forget to include "mmgr.h").
|
||||
|
||||
extern void* mmgr_malloc_dbg (size_t size, const char* file, int line, const char* func);
|
||||
extern void* mmgr_calloc_dbg (size_t num, size_t size, const char* file, int line, const char* func);
|
||||
extern void* mmgr_realloc_dbg(void* p, size_t size, const char* file, int line, const char* func);
|
||||
extern void mmgr_free_dbg (void* p, const char* file, int line, const char* func);
|
||||
|
||||
extern char* mmgr_strdup_dbg(const char*, const char* file, int line, const char* func);
|
||||
extern wchar_t* mmgr_wcsdup_dbg(const wchar_t*, const char* file, int line, const char* func);
|
||||
extern char* mmgr_getcwd_dbg(char*, size_t, const char* file, int line, const char* func);
|
||||
extern char* mmgr_strdup_dbg(const char*, const char* file, int line, const char* func);
|
||||
extern wchar_t* mmgr_wcsdup_dbg(const wchar_t*, const char* file, int line, const char* func);
|
||||
extern char* mmgr_getcwd_dbg(char*, size_t, const char* file, int line, const char* func);
|
||||
|
||||
|
||||
// .. global operator new (to catch allocs from STL/external libs)
|
||||
@ -148,9 +150,9 @@ extern void operator delete[](void* p, const char* file, int line, const char* f
|
||||
#define realloc(p,size) mmgr_realloc_dbg(p,size, __FILE__,__LINE__,__FUNCTION__)
|
||||
#define free(p) mmgr_free_dbg (p, __FILE__,__LINE__,__FUNCTION__)
|
||||
|
||||
#define strdup(p) mmgr_strdup_dbg(p, __FILE__,__LINE__,__FUNCTION__)
|
||||
#define wcsdup(p) mmgr_wcsdup_dbg(p, __FILE__,__LINE__,__FUNCTION__)
|
||||
#define getcwd(p,size) mmgr_getcwd_dbg(p, size, __FILE__,__LINE__,__FUNCTION__)
|
||||
#define strdup(p) mmgr_strdup_dbg(p, __FILE__,__LINE__,__FUNCTION__)
|
||||
#define wcsdup(p) mmgr_wcsdup_dbg(p, __FILE__,__LINE__,__FUNCTION__)
|
||||
#define getcwd(p,size) mmgr_getcwd_dbg(p, size, __FILE__,__LINE__,__FUNCTION__)
|
||||
|
||||
#endif // #ifdef USE_MMGR
|
||||
|
||||
@ -158,9 +160,8 @@ extern void operator delete[](void* p, const char* file, int line, const char* f
|
||||
// purpose and history
|
||||
// -------------------
|
||||
|
||||
// our goal is to expose any memory handling bugs in the
|
||||
// application as early as possible, by triggering
|
||||
// breakpoints when a problem is detected.
|
||||
// our goal is to expose any memory handling bugs in the application as
|
||||
// early as possible. various checks are performed upon each memory API call;
|
||||
// if all options are on, we can spot the following:
|
||||
// memory leaks, double-free, allocation over/underruns,
|
||||
// unused memory, and use-after-free.
|
||||
@ -175,6 +176,8 @@ extern void operator delete[](void* p, const char* file, int line, const char* f
|
||||
// ----------------------------------------------
|
||||
//
|
||||
// 1) #include this from all project source files [that will allocate memory].
|
||||
// doing so from the precompiled header is recommended, since the
|
||||
// compiler will make sure it has actually been included.
|
||||
// 2) all system headers must be #include-d before this header, so that
|
||||
// we don't mess with any of their local operator new/delete.
|
||||
// 3) if project source/headers also use local operator new/delete, #include
|
||||
@ -204,7 +207,7 @@ extern void operator delete[](void* p, const char* file, int line, const char* f
|
||||
// when tracking down hard-to-find bugs, more stringent checks can be
|
||||
// activated via mmgr_set_option, or by changing the initial value of
|
||||
// options in mmgr.cpp. however, they slow down the app considerably
|
||||
// and need not always be enabled. see option declarations below.
|
||||
// and need not always be enabled. see option declarations above.
|
||||
//
|
||||
// you can also change padding_size in mmgr.cpp at compile-time to provide
|
||||
// more safety vs. overruns, at the cost of wasting lots of memory per
|
||||
|
@ -779,7 +779,10 @@ static int dump_udt(DWORD type_idx, const u8* p, size_t size, uint level)
|
||||
|
||||
DWORD ofs = 0;
|
||||
if(!SymGetTypeInfo(hProcess, mod_base, child_data_idx, TI_GET_OFFSET, &ofs))
|
||||
debug_warn("dump_udt: warning: TI_GET_OFFSET query failed");
|
||||
// this happens if child_data_idx doesn't represent a member
|
||||
// variable of the UDT - e.g. a SymTagBaseClass. we don't bother
|
||||
// checking the tag; just skip this symbol.
|
||||
continue;
|
||||
|
||||
int ret = dump_data_sym(child_data_idx, p+ofs, level+1);
|
||||
|
||||
@ -801,7 +804,9 @@ static int dump_udt(DWORD type_idx, const u8* p, size_t size, uint level)
|
||||
// given a data symbol's type identifier, output its type name (if
|
||||
// applicable), determine what kind of variable it describes, and
|
||||
// call the appropriate dump_* routine.
|
||||
// lock is held.
|
||||
//
|
||||
// split out of dump_data_sym so we can recurse for typedefs (cleaner than
|
||||
// 'restart' via goto or loop). lock is held.
|
||||
static int dump_type_sym(DWORD type_idx, const u8* p, uint level)
|
||||
{
|
||||
DWORD type_tag;
|
||||
@ -863,6 +868,8 @@ static int dump_type_sym(DWORD type_idx, const u8* p, uint level)
|
||||
// lock is held.
|
||||
static int dump_data_sym(DWORD data_idx, const u8* p, uint level)
|
||||
{
|
||||
// note: return both type_idx and name in one call for convenience.
|
||||
// this is also more efficient than TI_GET_SYMNAME (avoids 1 LocalAlloc).
|
||||
SYMBOL_INFO_PACKAGEW sp;
|
||||
SYMBOL_INFOW* sym = &sp.si;
|
||||
sym->SizeOfStruct = sizeof(sp.si);
|
||||
@ -870,11 +877,13 @@ static int dump_data_sym(DWORD data_idx, const u8* p, uint level)
|
||||
if(!SymFromIndexW(hProcess, mod_base, data_idx, sym))
|
||||
return -1;
|
||||
|
||||
// one case where this happens is when called for all children of UDT:
|
||||
// that includes 'BaseClass' nodes.
|
||||
if(sym->Tag != SymTagData)
|
||||
{
|
||||
// shouldn't happen; dump_udt skips symbols that don't have defined
|
||||
// offset values. dump_sym_cb is the only other call site.
|
||||
assert(0 && "unexpected symbol tag in dump_data_sym");
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
// indent
|
||||
for(uint i = 0; i <= level+1; i++)
|
||||
|
Loading…
Reference in New Issue
Block a user