forked from 0ad/0ad
more of the asserts.. also:
- increase stack trace buffer size (needed for some complicated nested expressions) - fix bug in container output - no longer treat iterator (i.e. x::iterator) as an x string (now uses match_wildcard instead of simple string compare) - add unicode match_wildcard - bugfix for vectored exception handler - was always ignoring exceptions from main thread (fixed the previous fix where it was always grabbing all exceptions ;p) - better array display (display less of huge arrays) - fix nesting limit (which was too low); make sure infinite nesting/indirection can't happen This was SVN commit r2448.
This commit is contained in:
parent
ec6b78b252
commit
a1e149ab11
@ -37,7 +37,7 @@ wchar_t* debug_log_pos = debug_log;
|
||||
void debug_wprintf_mem(const wchar_t* fmt, ...)
|
||||
{
|
||||
const ssize_t chars_left = (ssize_t)LOG_CHARS - (debug_log_pos-debug_log);
|
||||
assert2(chars_left >= 0);
|
||||
debug_assert(chars_left >= 0);
|
||||
|
||||
// potentially not enough room for the new string; throw away the
|
||||
// older half of the log. we still protect against overflow below.
|
||||
@ -352,7 +352,7 @@ ErrorReaction display_error(const wchar_t* description, int flags,
|
||||
debug_wprintf(L"%hs(%d): %s\n", filename, line, description);
|
||||
|
||||
wchar_t* text;
|
||||
const size_t MAX_CHARS = 64*1024;
|
||||
const size_t MAX_CHARS = 512*1024;
|
||||
void* mem = malloc(MAX_CHARS*sizeof(wchar_t));
|
||||
if(mem)
|
||||
{
|
||||
|
@ -31,7 +31,7 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// check heap integrity (independently of mmgr).
|
||||
// errors are reported by the CRT, e.g. via assert.
|
||||
// errors are reported by the CRT, e.g. via debug_assert.
|
||||
extern void debug_heap_check(void);
|
||||
|
||||
enum DebugHeapChecks
|
||||
@ -51,7 +51,7 @@ extern void debug_heap_enable(DebugHeapChecks what);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// assert
|
||||
// debug_assert
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// notify the user that an assertion failed; displays a
|
||||
@ -59,8 +59,9 @@ extern void debug_heap_enable(DebugHeapChecks what);
|
||||
// returns one of UserErrorReaction.
|
||||
extern enum ErrorReaction debug_assert_failed(const char* source_file, int line, const char* assert_expr);
|
||||
|
||||
// recommended use: assert2(expr && "descriptive string")
|
||||
#define assert2(expr)\
|
||||
// recommended use: debug_assert(expr && "descriptive string")
|
||||
#undef debug_assert
|
||||
#define debug_assert(expr)\
|
||||
STMT(\
|
||||
static unsigned char suppress__ = 0x55;\
|
||||
if(suppress__ == 0x55 && !(expr))\
|
||||
@ -88,8 +89,8 @@ extern void debug_wprintf(const wchar_t* fmt, ...);
|
||||
// used for "last activity" reporting in the crashlog.
|
||||
extern void debug_wprintf_mem(const wchar_t* fmt, ...);
|
||||
|
||||
// warn of unexpected state. less error-prone than assert(!"text");
|
||||
#define debug_warn(str) assert2(0 && (str))
|
||||
// warn of unexpected state. less error-prone than debug_assert(!"text");
|
||||
#define debug_warn(str) debug_assert(0 && (str))
|
||||
|
||||
// TODO
|
||||
extern int debug_write_crashlog(const wchar_t* text);
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "debug_stl.h"
|
||||
#include "lib.h" // match_wildcardw
|
||||
|
||||
// portable debugging helper functions specific to the STL.
|
||||
|
||||
@ -62,7 +63,7 @@ void stl_simplify_name(char* name)
|
||||
else if(c == '>')
|
||||
{
|
||||
nesting--;
|
||||
assert(nesting >= 0);
|
||||
debug_assert(nesting >= 0);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@ -102,7 +103,7 @@ void stl_simplify_name(char* name)
|
||||
dst--;
|
||||
src += 15;
|
||||
// strip everything until trailing > is matched
|
||||
assert(nesting == 0);
|
||||
debug_assert(nesting == 0);
|
||||
nesting = 1;
|
||||
}
|
||||
else if(!strncmp(src, "std::less<", 10))
|
||||
@ -112,7 +113,7 @@ void stl_simplify_name(char* name)
|
||||
dst--;
|
||||
src += 10;
|
||||
// strip everything until trailing > is matched
|
||||
assert(nesting == 0);
|
||||
debug_assert(nesting == 0);
|
||||
nesting = 1;
|
||||
}
|
||||
STRIP("std::")
|
||||
@ -309,7 +310,7 @@ class Any_string : public std::string
|
||||
public:
|
||||
bool valid(size_t el_size) const
|
||||
{
|
||||
assert(el_size == sizeof(char));
|
||||
debug_assert(el_size == sizeof(char));
|
||||
if(!container_valid(c_str(), size()))
|
||||
return false;
|
||||
#if STL_DINKUMWARE != 0
|
||||
@ -329,7 +330,7 @@ class Any_wstring : public std::wstring
|
||||
public:
|
||||
bool valid(size_t el_size) const
|
||||
{
|
||||
assert(el_size == sizeof(wchar_t));
|
||||
debug_assert(el_size == sizeof(wchar_t));
|
||||
if(!container_valid(c_str(), size()))
|
||||
return false;
|
||||
#if STL_DINKUMWARE != 0
|
||||
@ -353,8 +354,9 @@ public:
|
||||
template<class T> bool get_container_info(T* t, size_t size, size_t el_size,
|
||||
size_t* el_count, DebugIterator* el_iterator, void* it_mem)
|
||||
{
|
||||
assert(sizeof(T) == size);
|
||||
assert(sizeof(T::iterator) < DEBUG_STL_MAX_ITERATOR_SIZE);
|
||||
if(sizeof(T) != size)
|
||||
debug_assert(sizeof(T) == size);
|
||||
debug_assert(sizeof(T::iterator) < DEBUG_STL_MAX_ITERATOR_SIZE);
|
||||
|
||||
*el_count = t->size();
|
||||
*el_iterator = stl_iterator<T>;
|
||||
@ -375,7 +377,7 @@ int stl_get_container_info(const wchar_t* type_name, const u8* p, size_t size,
|
||||
bool valid;
|
||||
|
||||
#define CONTAINER(name)\
|
||||
else if(!wcsncmp(type_name, L"std::" L###name, wcslen(L###name)+5))\
|
||||
else if(match_wildcardw(type_name, L"std::" L###name L"<*>"))\
|
||||
valid = get_container_info<Any_##name>((Any_##name*)p, size, el_size, el_count, el_iterator, it_mem);
|
||||
|
||||
if(0) {} // kickoff
|
||||
@ -386,9 +388,9 @@ int stl_get_container_info(const wchar_t* type_name, const u8* p, size_t size,
|
||||
CONTAINER(set)
|
||||
CONTAINER(stack)
|
||||
CONTAINER(vector)
|
||||
else if(!wcsncmp(type_name, L"std::basic_string<char", 22))
|
||||
else if(match_wildcardw(type_name, L"std::basic_string<char*>"))
|
||||
valid = get_container_info<Any_string>((Any_string*)p, size, el_size, el_count, el_iterator, it_mem);
|
||||
else if(!wcsncmp(type_name, L"std::basic_string<unsigned short", 32))
|
||||
else if(match_wildcardw(type_name, L"std::basic_string<unsigned short*>"))
|
||||
valid = get_container_info<Any_wstring>((Any_wstring*)p, size, el_size, el_count, el_iterator, it_mem);
|
||||
// unknown type, can't handle it
|
||||
else
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@ -202,9 +202,9 @@ int ilog2(const float x)
|
||||
// multiple must be a power of two.
|
||||
uintptr_t round_up(const uintptr_t n, const uintptr_t multiple)
|
||||
{
|
||||
assert(is_pow2((long)multiple)); // also catches divide-by-zero
|
||||
debug_assert(is_pow2((long)multiple)); // also catches divide-by-zero
|
||||
const uintptr_t result = (n + multiple-1) & ~(multiple-1);
|
||||
assert(n <= result && result < n+multiple);
|
||||
debug_assert(n <= result && result < n+multiple);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -277,7 +277,7 @@ u8 fp_to_u8(double in)
|
||||
}
|
||||
|
||||
int l = (int)(in * 255.0);
|
||||
assert((unsigned int)l <= 255u);
|
||||
debug_assert((unsigned int)l <= 255u);
|
||||
return (u8)l;
|
||||
}
|
||||
|
||||
@ -292,7 +292,7 @@ u16 fp_to_u16(double in)
|
||||
}
|
||||
|
||||
long l = (long)(in * 65535.0);
|
||||
assert((unsigned long)l <= 65535u);
|
||||
debug_assert((unsigned long)l <= 65535u);
|
||||
return (u16)l;
|
||||
}
|
||||
|
||||
@ -306,7 +306,7 @@ int rand_up_to(int limit)
|
||||
{
|
||||
// (i64 avoids overflowing in multiply)
|
||||
const i64 ret = ((i64)limit * rand()) / (RAND_MAX+1);
|
||||
assert2(0 <= ret && ret < limit);
|
||||
debug_assert(0 <= ret && ret < limit);
|
||||
return (int)ret;
|
||||
}
|
||||
|
||||
@ -391,3 +391,52 @@ int match_wildcard(const char* s, const char* w)
|
||||
|
||||
return (*w == '\0');
|
||||
}
|
||||
|
||||
int match_wildcardw(const wchar_t* s, const wchar_t* w)
|
||||
{
|
||||
if(!w)
|
||||
return 1;
|
||||
|
||||
// saved position in both strings, used to expand '*':
|
||||
// s2 is advanced until match.
|
||||
// initially 0 - we abort on mismatch before the first '*'.
|
||||
const wchar_t* s2 = 0;
|
||||
const wchar_t* w2 = 0;
|
||||
|
||||
while(*s)
|
||||
{
|
||||
const wchar_t wc = *w;
|
||||
if(wc == '*')
|
||||
{
|
||||
// wildcard string ended with * => match.
|
||||
if(*++w == '\0')
|
||||
return 1;
|
||||
|
||||
w2 = w;
|
||||
s2 = s+1;
|
||||
}
|
||||
// match one character
|
||||
else if(towupper(wc) == towupper(*s) || wc == '?')
|
||||
{
|
||||
w++;
|
||||
s++;
|
||||
}
|
||||
// mismatched character
|
||||
else
|
||||
{
|
||||
// no '*' found yet => mismatch.
|
||||
if(!s2)
|
||||
return 0;
|
||||
|
||||
// resume at previous position+1
|
||||
w = w2;
|
||||
s = s2++;
|
||||
}
|
||||
}
|
||||
|
||||
// strip trailing * in wildcard string
|
||||
while(*w == '*')
|
||||
w++;
|
||||
|
||||
return (*w == '\0');
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ scope
|
||||
#define LIB_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include "lib/types.h"
|
||||
@ -107,7 +107,7 @@ STMT(\
|
||||
int err__ = (int)((func) & UINT_MAX);\
|
||||
if(err__ < 0)\
|
||||
{\
|
||||
assert2(0 && "FYI: CHECK_ERR reports that a function failed."\
|
||||
debug_assert(0 && "FYI: CHECK_ERR reports that a function failed."\
|
||||
"feel free to ignore or suppress this warning.");\
|
||||
return err__;\
|
||||
}\
|
||||
@ -139,7 +139,7 @@ STMT(\
|
||||
int err__ = (int)((func) & UINT_MAX);\
|
||||
if(err__ < 0)\
|
||||
{\
|
||||
assert(0 && "FYI: CHECK_ERR reports that a function failed."\
|
||||
debug_assert(0 && "FYI: CHECK_ERR reports that a function failed."\
|
||||
"feel free to ignore or suppress this warning.");\
|
||||
throw err__;\
|
||||
}\
|
||||
@ -231,7 +231,7 @@ enum LibError
|
||||
|
||||
|
||||
//
|
||||
// compile-time assert, especially useful for testing sizeof().
|
||||
// compile-time debug_assert, especially useful for testing sizeof().
|
||||
// no runtime overhead; may be used anywhere, including file scope.
|
||||
//
|
||||
|
||||
@ -332,6 +332,6 @@ extern void base32(const int len, const u8* in, u8* out);
|
||||
// which may contain '?' or '*' wildcards. if so, return 1, otherwise 0.
|
||||
// note: NULL wildcard pattern matches everything!
|
||||
extern int match_wildcard(const char* s, const char* w);
|
||||
|
||||
extern int match_wildcardw(const wchar_t* s, const wchar_t* w);
|
||||
|
||||
#endif // #ifndef LIB_H__
|
||||
|
@ -37,6 +37,10 @@
|
||||
WIN_REGISTER_FUNC(wdbg_init);
|
||||
#pragma data_seg()
|
||||
|
||||
// used to prevent the vectored exception handler from taking charge when
|
||||
// an exception is raised from the main thread (allows __try blocks to
|
||||
// get control). latched in wdbg_init.
|
||||
static DWORD main_thread_id;
|
||||
|
||||
|
||||
// protects the breakpoint helper thread.
|
||||
@ -171,7 +175,7 @@ void debug_heap_enable(DebugHeapChecks what)
|
||||
_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF;
|
||||
break;
|
||||
default:
|
||||
assert2("debug_heap_enable: invalid what");
|
||||
debug_assert("debug_heap_enable: invalid what");
|
||||
}
|
||||
_CrtSetDbgFlag(flags);
|
||||
#endif // HAVE_DEBUGALLOC
|
||||
@ -212,7 +216,7 @@ static void* while_suspended_thread_func(void* user_arg)
|
||||
int ret = param->func(param->hThread, param->user_arg);
|
||||
|
||||
err = ResumeThread(param->hThread);
|
||||
assert(err != 0);
|
||||
debug_assert(err != 0);
|
||||
|
||||
return (void*)(intptr_t)ret;
|
||||
|
||||
@ -241,11 +245,11 @@ static int call_while_suspended(WhileSuspendedFunc func, void* user_arg)
|
||||
|
||||
pthread_t thread;
|
||||
err = pthread_create(&thread, 0, while_suspended_thread_func, ¶m);
|
||||
assert2(err == 0);
|
||||
debug_assert(err == 0);
|
||||
|
||||
void* ret;
|
||||
err = pthread_join(thread, &ret);
|
||||
assert2(err == 0 && ret == 0);
|
||||
debug_assert(err == 0 && ret == 0);
|
||||
|
||||
return (int)(intptr_t)ret;
|
||||
}
|
||||
@ -921,10 +925,10 @@ static const wchar_t* get_exception_locus(const EXCEPTION_POINTERS* ep)
|
||||
|
||||
// called* when an SEH exception was not caught by the app;
|
||||
// provides detailed debugging information and exits.
|
||||
// (via win.cpp!entry's __except or as a vectored handler; see below)
|
||||
// (via win.cpp!entry's __except or vectored_exception_handler; see below)
|
||||
//
|
||||
// note: keep memory allocs and lock usage to an absolute minimum, because we may
|
||||
// deadlock the process
|
||||
// note: keep memory allocs and locking to an absolute minimum, because
|
||||
// they may deadlock the process!
|
||||
//
|
||||
// rationale:
|
||||
// we want to replace the OS "program error" dialog box because
|
||||
@ -1006,7 +1010,7 @@ LONG WINAPI wdbg_exception_filter(EXCEPTION_POINTERS* ep)
|
||||
if(ep->ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE)
|
||||
flags = DE_NO_CONTINUE;
|
||||
ErrorReaction er = display_error(buf, flags, 1, ep->ContextRecord, file, line);
|
||||
assert(er > 0);
|
||||
debug_assert(er > 0);
|
||||
|
||||
wdbg_write_minidump(ep);
|
||||
|
||||
@ -1016,8 +1020,23 @@ LONG WINAPI wdbg_exception_filter(EXCEPTION_POINTERS* ep)
|
||||
}
|
||||
|
||||
|
||||
static LONG WINAPI vectored_exception_handler(EXCEPTION_POINTERS* ep)
|
||||
{
|
||||
// since we're called from the vectored handler chain,
|
||||
// ignore exceptions from the main thread. this allows
|
||||
// __try blocks to take charge; entry() catches all exceptions with a
|
||||
// standard filter and relays them to wdbg_exception_filter.
|
||||
if(main_thread_id == GetCurrentThreadId())
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
return wdbg_exception_filter(ep);
|
||||
}
|
||||
|
||||
|
||||
static int wdbg_init(void)
|
||||
{
|
||||
// see decl
|
||||
main_thread_id = GetCurrentThreadId();
|
||||
|
||||
// add vectored exception handler (if supported by the OS).
|
||||
// see rationale above.
|
||||
#if _WIN32_WINNT >= 0x0500 // this is how winbase.h tests for it
|
||||
@ -1029,7 +1048,7 @@ static int wdbg_init(void)
|
||||
// doesn't complain. it won't actually be unloaded anyway -
|
||||
// there is at least one other reference.
|
||||
if(pAddVectoredExceptionHandler)
|
||||
pAddVectoredExceptionHandler(TRUE, wdbg_exception_filter);
|
||||
pAddVectoredExceptionHandler(TRUE, vectored_exception_handler);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// stack trace, improved assert and exception handler for Win32
|
||||
// stack trace, improved debug_assert and exception handler for Win32
|
||||
// Copyright (c) 2002-2005 Jan Wassenberg
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
|
@ -1,4 +1,4 @@
|
||||
// stack trace, improved assert and exception handler for Win32
|
||||
// stack trace, improved debug_assert and exception handler for Win32
|
||||
// Copyright (c) 2002-2005 Jan Wassenberg
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
@ -48,11 +48,9 @@ WIN_REGISTER_FUNC(wdbg_sym_shutdown);
|
||||
#pragma data_seg()
|
||||
|
||||
|
||||
// debug_warn usually uses assert2, but we don't want to call that from
|
||||
// inside an assert2 (from inside another assert2 (from inside another assert2
|
||||
// (... etc))), so just use the normal assert
|
||||
//#undef debug_warn
|
||||
//#define debug_warn(str) assert(0 && (str))
|
||||
// note: it is safe to use debug_assert/debug_warn/CHECK_ERR even during a
|
||||
// stack trace (which is triggered by debug_assert et al. in app code) because
|
||||
// nested stack traces are ignored and only the error is displayed.
|
||||
|
||||
|
||||
// protects dbghelp (which isn't thread-safe) and
|
||||
@ -84,6 +82,10 @@ enum WdbgError
|
||||
// an essential call to SymGetTypeInfo or SymFromIndex failed.
|
||||
WDBG_TYPE_INFO_UNAVAILABLE = -100102,
|
||||
|
||||
// a generous limit on nesting depth has been reached.
|
||||
// we abort to make sure we don't recurse infinitely.
|
||||
WDBG_NESTING_LIMIT = -100103,
|
||||
|
||||
// exception raised while processing the symbol.
|
||||
WDBG_INTERNAL_ERROR = -100200,
|
||||
|
||||
@ -130,7 +132,7 @@ static int sym_init()
|
||||
SymSetOptions(SYMOPT_DEFERRED_LOADS/*/*|SYMOPT_DEBUG*/);
|
||||
// loads symbols for all active modules.
|
||||
BOOL ok = SymInitialize(hProcess, 0, TRUE);
|
||||
assert2(ok);
|
||||
debug_assert(ok);
|
||||
|
||||
mod_base = SymGetModuleBase64(hProcess, (u64)&sym_init);
|
||||
IMAGE_NT_HEADERS* header = ImageNtHeader((void*)mod_base);
|
||||
@ -222,7 +224,7 @@ int debug_resolve_symbol(void* ptr_of_interest, char* sym_name, char* file, int*
|
||||
// rationale: to function properly, StackWalk64 requires a CONTEXT on
|
||||
// non-x86 systems (documented) or when in release mode (observed).
|
||||
// exception handlers can call walk_stack with their context record;
|
||||
// otherwise (e.g. dump_stack from assert2), we need to query it.
|
||||
// otherwise (e.g. dump_stack from debug_assert), we need to query it.
|
||||
// there are 2 platform-independent ways to do so:
|
||||
// - intentionally raise an SEH exception, then proceed as above;
|
||||
// - GetThreadContext while suspended (*).
|
||||
@ -442,9 +444,10 @@ void* debug_get_nth_caller(uint n)
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// overflow is impossible in practice. keep in sync with DumpState.
|
||||
static const uint MAX_INDIRECTION = 256;
|
||||
static const uint MAX_LEVEL = 256;
|
||||
// overflow is impossible in practice, but check for robustness.
|
||||
// keep in sync with DumpState.
|
||||
static const uint MAX_INDIRECTION = 255;
|
||||
static const uint MAX_LEVEL = 255;
|
||||
|
||||
struct DumpState
|
||||
{
|
||||
@ -693,10 +696,25 @@ static int dump_sequence(DebugIterator el_iterator, void* internal,
|
||||
return ret;
|
||||
|
||||
out(L"[%d] ", el_count);
|
||||
const size_t num_elements_to_show = MIN(20, el_count);
|
||||
const bool fits_on_one_line =
|
||||
(el_size == sizeof(char) && el_count <= 16) ||
|
||||
(el_size <= sizeof(int ) && el_count <= 8);
|
||||
|
||||
// choose formatting based on element size
|
||||
bool fits_on_one_line;
|
||||
size_t num_elements_to_show;
|
||||
if(el_size == sizeof(char))
|
||||
{
|
||||
fits_on_one_line = el_count <= 16;
|
||||
num_elements_to_show = MIN(16, el_count);
|
||||
}
|
||||
else if(el_size <= sizeof(int))
|
||||
{
|
||||
fits_on_one_line = el_count <= 8;
|
||||
num_elements_to_show = MIN(12, el_count);
|
||||
}
|
||||
else
|
||||
{
|
||||
fits_on_one_line = false;
|
||||
num_elements_to_show = MIN(8, el_count);
|
||||
}
|
||||
|
||||
state.level++;
|
||||
out(fits_on_one_line? L"{ " : L"\r\n");
|
||||
@ -872,9 +890,9 @@ static int dump_sym_array(DWORD type_id, const u8* p, DumpState state)
|
||||
if(!SymGetTypeInfo(hProcess, mod_base, el_type_id, TI_GET_LENGTH, &el_size_))
|
||||
return WDBG_TYPE_INFO_UNAVAILABLE;
|
||||
const size_t el_size = (size_t)el_size_;
|
||||
assert(el_size != 0);
|
||||
debug_assert(el_size != 0);
|
||||
const size_t num_elements = size/el_size;
|
||||
assert2(num_elements != 0);
|
||||
debug_assert(num_elements != 0);
|
||||
|
||||
return dump_array(p, num_elements, el_type_id, el_size, state);
|
||||
}
|
||||
@ -912,7 +930,7 @@ static int dump_sym_base_type(DWORD type_id, const u8* p, DumpState state)
|
||||
{
|
||||
// boolean
|
||||
case btBool:
|
||||
assert(size == sizeof(bool));
|
||||
debug_assert(size == sizeof(bool));
|
||||
fmt = L"%hs";
|
||||
data = (u64)(data? "true " : "false");
|
||||
break;
|
||||
@ -968,7 +986,7 @@ display_as_hex:
|
||||
// character
|
||||
case btChar:
|
||||
case btWChar:
|
||||
assert(size == sizeof(char) || size == sizeof(wchar_t));
|
||||
debug_assert(size == sizeof(char) || size == sizeof(wchar_t));
|
||||
// char*, wchar_t*
|
||||
if(state.indirection)
|
||||
{
|
||||
@ -1006,7 +1024,7 @@ display_as_hex:
|
||||
case btBit:
|
||||
case btBSTR:
|
||||
case btHresult:
|
||||
return -1;
|
||||
return WDBG_UNSUPPORTED;
|
||||
}
|
||||
|
||||
out(fmt, data);
|
||||
@ -1221,6 +1239,10 @@ static int dump_sym_pointer(DWORD type_id, const u8* p, DumpState state)
|
||||
out(L" -> ");
|
||||
if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_TYPEID, &type_id))
|
||||
return WDBG_TYPE_INFO_UNAVAILABLE;
|
||||
|
||||
// prevent infinite recursion just to be safe (shouldn't happen)
|
||||
if(state.indirection >= MAX_INDIRECTION)
|
||||
return WDBG_NESTING_LIMIT;
|
||||
state.indirection++;
|
||||
return dump_sym(type_id, p, state);
|
||||
}
|
||||
@ -1431,9 +1453,10 @@ static int udt_dump_normal(const wchar_t* type_name, const u8* p, size_t size,
|
||||
{
|
||||
const bool fits_on_one_line = udt_fits_on_one_line(type_name, num_children, size);
|
||||
|
||||
// prevent infinite recursion just to be safe (shouldn't happen)
|
||||
if(state.level >= MAX_LEVEL)
|
||||
return WDBG_NESTING_LIMIT;
|
||||
state.level++;
|
||||
if(state.level > 20)
|
||||
return -1;
|
||||
|
||||
out(fits_on_one_line? L"{ " : L"\r\n");
|
||||
|
||||
@ -1447,7 +1470,7 @@ static int udt_dump_normal(const wchar_t* type_name, const u8* p, size_t size,
|
||||
DWORD ofs = 0;
|
||||
if(!SymGetTypeInfo(hProcess, mod_base, child_id, TI_GET_OFFSET, &ofs))
|
||||
continue;
|
||||
assert(ofs < size);
|
||||
debug_assert(ofs < size);
|
||||
|
||||
if(!fits_on_one_line)
|
||||
INDENT;
|
||||
@ -1698,8 +1721,8 @@ const wchar_t* debug_dump_stack(wchar_t* buf, size_t max_chars, uint skip, void*
|
||||
if(!CAS(&already_in_progress, 0, 1))
|
||||
{
|
||||
wcscpy_s(buf, max_chars,
|
||||
L"(cannot start a nested stack trace; what probably happened is that"
|
||||
L"an assert/debug_warn/CHECK_ERR fired during the current trace.)"
|
||||
L"(cannot start a nested stack trace; what probably happened is that "
|
||||
L"an debug_assert/debug_warn/CHECK_ERR fired during the current trace.)"
|
||||
);
|
||||
return buf;
|
||||
}
|
||||
@ -1823,7 +1846,7 @@ Small small_array_of_small_structs[2] = { { 1,2 } };
|
||||
int ar1[] = { 1,2,3,4,5 };
|
||||
char ar2[] = { 't','e','s','t', 0 };
|
||||
|
||||
//assert2(0 && "test assert2"); // not exception (works when run from debugger)
|
||||
//debug_assert(0 && "test debug_assert"); // not exception (works when run from debugger)
|
||||
//__asm xor edx,edx __asm div edx // named SEH
|
||||
//RaiseException(0x87654321, 0, 0, 0); // unknown SEH
|
||||
//throw std::bad_exception("what() is ok"); // C++
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> // __argc
|
||||
|
||||
@ -158,7 +158,7 @@ static int CALLBACK browse_cb(HWND hWnd, unsigned int msg, LPARAM lParam, LPARAM
|
||||
|
||||
int pick_directory(char* path, size_t buf_size)
|
||||
{
|
||||
assert(buf_size >= PATH_MAX);
|
||||
debug_assert(buf_size >= PATH_MAX);
|
||||
IMalloc* p_malloc;
|
||||
SHGetMalloc(&p_malloc);
|
||||
|
||||
@ -185,7 +185,7 @@ int pick_directory(char* path, size_t buf_size)
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// "program error" dialog (triggered by assert and exception)
|
||||
// "program error" dialog (triggered by debug_assert and exception)
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// support for resizing the dialog / its controls
|
||||
@ -563,21 +563,21 @@ static bool cs_valid;
|
||||
|
||||
void win_lock(uint idx)
|
||||
{
|
||||
assert(idx < NUM_CS && "win_lock: invalid critical section index");
|
||||
debug_assert(idx < NUM_CS && "win_lock: invalid critical section index");
|
||||
if(cs_valid)
|
||||
EnterCriticalSection(&cs[idx]);
|
||||
}
|
||||
|
||||
void win_unlock(uint idx)
|
||||
{
|
||||
assert(idx < NUM_CS && "win_unlock: invalid critical section index");
|
||||
debug_assert(idx < NUM_CS && "win_unlock: invalid critical section index");
|
||||
if(cs_valid)
|
||||
LeaveCriticalSection(&cs[idx]);
|
||||
}
|
||||
|
||||
int win_is_locked(uint idx)
|
||||
{
|
||||
assert(idx < NUM_CS && "win_is_locked: invalid critical section index");
|
||||
debug_assert(idx < NUM_CS && "win_is_locked: invalid critical section index");
|
||||
if(!cs_valid)
|
||||
return -1;
|
||||
BOOL got_it = TryEnterCriticalSection(&cs[idx]);
|
||||
@ -637,7 +637,7 @@ uint local2 = 0x1234;
|
||||
debug_printf("&static2 = %p\n", &static2);
|
||||
debug_printf("param2 = %p\n&local2 = %p\n", param2, &local2);
|
||||
debug_printf("¶m2a = %p\nparam2b = %p\nparam2c = %p\n", ¶m2a, ¶m2b, ¶m2c);
|
||||
assert2(0 == 1);
|
||||
debug_assert(0 == 1);
|
||||
}
|
||||
|
||||
static void test1(uint param1a, uint param1b, uint param1c, std::vector<uint>* param1)
|
||||
|
Loading…
Reference in New Issue
Block a user