forked from 0ad/0ad
wdbg, wposix, wsdl: fix some VC2005 warnings
wdbg_sym: prevent nested trees/arrays from hogging too much buffer space This was SVN commit r2471.
This commit is contained in:
parent
3d23b2d9f5
commit
9bf5316b72
@ -146,15 +146,22 @@ void debug_wprintf(const wchar_t* fmt, ...)
|
||||
// debug memory allocator
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// check heap integrity (independently of mmgr).
|
||||
// errors are reported by the CRT or via display_error.
|
||||
void debug_heap_check()
|
||||
{
|
||||
int ret;
|
||||
__try
|
||||
{
|
||||
_heapchk();
|
||||
ret = _heapchk();
|
||||
}
|
||||
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
ret = _HEAPBADNODE;
|
||||
}
|
||||
|
||||
if(ret != _HEAPOK)
|
||||
DISPLAY_ERROR(L"debug_heap_check: heap is corrupt");
|
||||
}
|
||||
|
||||
|
||||
@ -746,7 +753,7 @@ static int screwaround()
|
||||
//
|
||||
|
||||
// storage for strings built by get_SEH_exception_description and get_cpp_exception_description.
|
||||
static wchar_t description[128];
|
||||
static wchar_t description_buf[128];
|
||||
|
||||
// VC++ exception handling internals.
|
||||
// see http://www.codeproject.com/cpp/exceptionhandler.asp
|
||||
@ -841,8 +848,8 @@ static const wchar_t* get_cpp_exception_description(const EXCEPTION_RECORD* er)
|
||||
// we got meaningful data; format and return it.
|
||||
if(type_name[0] != '\0' || what[0] != '\0')
|
||||
{
|
||||
swprintf(description, ARRAY_SIZE(description), L"%hs(\"%hs\")", type_name, what);
|
||||
return description;
|
||||
swprintf(description_buf, ARRAY_SIZE(description_buf), L"%hs(\"%hs\")", type_name, what);
|
||||
return description_buf;
|
||||
}
|
||||
|
||||
// not a C++ exception; we can't say anything about it.
|
||||
@ -862,8 +869,8 @@ static const wchar_t* get_SEH_exception_description(const EXCEPTION_RECORD* er)
|
||||
{
|
||||
const wchar_t* op = (ei[0])? L"writing" : L"reading";
|
||||
const wchar_t* fmt = L"Access violation %s 0x%08X";
|
||||
swprintf(description, ARRAY_SIZE(description), translate(fmt), translate(op), ei[1]);
|
||||
return description;
|
||||
swprintf(description_buf, ARRAY_SIZE(description_buf), translate(fmt), translate(op), ei[1]);
|
||||
return description_buf;
|
||||
}
|
||||
|
||||
// rationale: we don't use FormatMessage because it is unclear whether
|
||||
@ -900,8 +907,8 @@ static const wchar_t* get_SEH_exception_description(const EXCEPTION_RECORD* er)
|
||||
// anything else => unknown; display its exception code.
|
||||
// we don't punt to get_exception_description because anything
|
||||
// we get called for will actually be a SEH exception.
|
||||
swprintf(description, ARRAY_SIZE(description), L"Unknown (0x%08X)", code);
|
||||
return description;
|
||||
swprintf(description_buf, ARRAY_SIZE(description_buf), L"Unknown (0x%08X)", code);
|
||||
return description_buf;
|
||||
}
|
||||
|
||||
|
||||
@ -928,7 +935,8 @@ static const wchar_t* get_exception_locus(const EXCEPTION_POINTERS* ep)
|
||||
// points to kernel32!RaiseException. we use debug_dump_stack to determine the
|
||||
// real location.
|
||||
|
||||
wchar_t buf[32000]; // Maybe TODO: "warning C6262: Function uses '64016' bytes of stack: exceeds /analysis:stacksize'16384'. Consider moving some data to heap"
|
||||
wchar_t buf[1000];
|
||||
// we only want the beginning and this is guarded against overflow.
|
||||
const wchar_t* stack_trace = debug_dump_stack(buf, ARRAY_SIZE(buf), 1, ep->ContextRecord);
|
||||
|
||||
const size_t MAX_LOCUS_CHARS = 256;
|
||||
|
@ -90,6 +90,11 @@ enum WdbgError
|
||||
// we abort to make sure we don't recurse infinitely.
|
||||
WDBG_NESTING_LIMIT = -100103,
|
||||
|
||||
// too much output has been produced by this top-level symbol;
|
||||
// we must terminate recursion lest it hog all buffer space.
|
||||
// dump will continue with the next top-level symbol.
|
||||
WDBG_SINGLE_SYMBOL_LIMIT = -100104,
|
||||
|
||||
// exception raised while processing the symbol.
|
||||
WDBG_INTERNAL_ERROR = -100200,
|
||||
|
||||
@ -479,9 +484,26 @@ struct DumpState
|
||||
|
||||
|
||||
static ssize_t out_chars_left;
|
||||
static wchar_t* out_pos;
|
||||
static bool out_have_warned_of_overflow;
|
||||
// only do so once until next out_init to avoid flood of messages.
|
||||
static wchar_t* out_pos;
|
||||
|
||||
// some top-level (*) symbols cause tons of output - so much that they may
|
||||
// single-handedly overflow the buffer (e.g. pointer to a tree of huge UDTs).
|
||||
// we can't have that, so there is a limit in place as to how much a
|
||||
// single top-level symbol can output. after that is reached, dumping is
|
||||
// aborted for that symbol but continues for the subsequent top-level symbols.
|
||||
//
|
||||
// this is implemented as follows: dump_sym_cb latches the current output
|
||||
// position; each dump_sym (through which all symbols go) checks if the
|
||||
// new position exceeds the limit and aborts if so.
|
||||
// slight wrinkle: since we don't want each level of UDTs to successively
|
||||
// realize the limit has been hit and display the error message, we
|
||||
// return WDBG_SINGLE_SYMBOL_LIMIT once and thereafter WDBG_SUPPRESS_OUTPUT.
|
||||
//
|
||||
// * example: local variables, as opposed to child symbols in a UDT.
|
||||
static wchar_t* out_latched_pos;
|
||||
static bool out_have_warned_of_limit;
|
||||
|
||||
static void out_init(wchar_t* buf, size_t max_chars)
|
||||
{
|
||||
@ -534,6 +556,30 @@ static void out_erase(size_t num_chars)
|
||||
}
|
||||
|
||||
|
||||
// (see above)
|
||||
static void out_latch_pos()
|
||||
{
|
||||
out_have_warned_of_limit = false;
|
||||
out_latched_pos = out_pos;
|
||||
}
|
||||
|
||||
|
||||
// (see above)
|
||||
static int out_check_limit()
|
||||
{
|
||||
if(out_have_warned_of_limit)
|
||||
return WDBG_SUPPRESS_OUTPUT;
|
||||
if(out_pos - out_latched_pos > 3000) // ~30 lines
|
||||
{
|
||||
out_have_warned_of_limit = true;
|
||||
return WDBG_SINGLE_SYMBOL_LIMIT;
|
||||
}
|
||||
|
||||
// no limit hit, proceed normally
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define INDENT STMT(for(uint i = 0; i <= state.level; i++) out(L" ");)
|
||||
#define UNINDENT STMT(out_erase((state.level+1)*4);)
|
||||
|
||||
@ -633,6 +679,9 @@ static void dump_error(int err, const u8* p)
|
||||
case 0:
|
||||
// no error => no output
|
||||
break;
|
||||
case WDBG_SINGLE_SYMBOL_LIMIT:
|
||||
out(L"(too much output; skipping to next top-level symbol)");
|
||||
break;
|
||||
case WDBG_UNRETRIEVABLE_STATIC:
|
||||
out(L"(unavailable - located in another module)");
|
||||
break;
|
||||
@ -745,26 +794,32 @@ static int dump_sequence(DebugIterator el_iterator, void* internal,
|
||||
INDENT;
|
||||
|
||||
int err = dump_sym(el_type_id, el_p, state);
|
||||
dump_error(err, el_p);
|
||||
el_p = el_iterator(internal, el_size);
|
||||
|
||||
// there was no output for this child; undo its indentation (if any),
|
||||
// skip everything below and proceed with the next child.
|
||||
if(err == WDBG_SUPPRESS_OUTPUT)
|
||||
{
|
||||
if(!fits_on_one_line)
|
||||
UNINDENT;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// add separator unless this is the last element (can't just
|
||||
// erase below due to additional "...").
|
||||
if(i != num_elements_to_show-1)
|
||||
out(fits_on_one_line? L", " : L"\r\n");
|
||||
}
|
||||
}
|
||||
// we truncated some
|
||||
|
||||
dump_error(err, el_p); // nop if err == 0
|
||||
// add separator unless this is the last element (can't just
|
||||
// erase below due to additional "...").
|
||||
if(i != num_elements_to_show-1)
|
||||
out(fits_on_one_line? L", " : L"\r\n");
|
||||
|
||||
if(err == WDBG_SINGLE_SYMBOL_LIMIT)
|
||||
break;
|
||||
} // for each child
|
||||
|
||||
// indicate some elements were skipped
|
||||
if(el_count != num_elements_to_show)
|
||||
out(L" ...");
|
||||
|
||||
state.level--;
|
||||
if(fits_on_one_line)
|
||||
out(L" }");
|
||||
return 0;
|
||||
@ -1499,19 +1554,23 @@ static int udt_dump_normal(const wchar_t* type_name, const u8* p, size_t size,
|
||||
|
||||
const u8* el_p = p+ofs;
|
||||
int err = dump_sym(child_id, el_p, state);
|
||||
dump_error(err, el_p);
|
||||
|
||||
// there was no output for this child; undo its indentation (if any),
|
||||
// skip everything below and proceed with the next child.
|
||||
if(err == WDBG_SUPPRESS_OUTPUT)
|
||||
{
|
||||
if(!fits_on_one_line)
|
||||
UNINDENT;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
out(fits_on_one_line? L", " : L"\r\n");
|
||||
displayed_anything = true;
|
||||
}
|
||||
}
|
||||
|
||||
displayed_anything = true;
|
||||
dump_error(err, el_p); // nop if err == 0
|
||||
out(fits_on_one_line? L", " : L"\r\n");
|
||||
|
||||
if(err == WDBG_SINGLE_SYMBOL_LIMIT)
|
||||
break;
|
||||
} // for each child
|
||||
|
||||
state.level--;
|
||||
|
||||
@ -1611,6 +1670,10 @@ static int dump_sym_unknown(DWORD type_id, const u8* p, DumpState state)
|
||||
// delegates to dump_sym_* depending on the symbol's tag.
|
||||
static int dump_sym(DWORD type_id, const u8* p, DumpState state)
|
||||
{
|
||||
int ret = out_check_limit();
|
||||
if(ret != 0)
|
||||
return ret;
|
||||
|
||||
DWORD type_tag;
|
||||
if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_SYMTAG, &type_tag))
|
||||
return WDBG_TYPE_INFO_UNAVAILABLE;
|
||||
@ -1654,6 +1717,7 @@ static int dump_sym(DWORD type_id, const u8* p, DumpState state)
|
||||
// called from dump_frame_cb for each local symbol; lock is held.
|
||||
static BOOL CALLBACK dump_sym_cb(SYMBOL_INFO* sym, ULONG size, void* ctx)
|
||||
{
|
||||
out_latch_pos(); // see decl
|
||||
mod_base = sym->ModBase;
|
||||
const u8* p = (const u8*)sym->Address;
|
||||
DumpState state;
|
||||
|
@ -218,8 +218,9 @@ static void detect_filesystem()
|
||||
// if this fails, no problem - we have the default from above.
|
||||
root_path[3] = '\0'; // cut off after "c:\"
|
||||
|
||||
char fs_name[32];
|
||||
char fs_name[32] = {0};
|
||||
BOOL ret = GetVolumeInformation(root_path, 0,0,0,0,0, fs_name, sizeof(fs_name));
|
||||
fs_name[ARRAY_SIZE(fs_name)-1] = '\0';
|
||||
debug_assert(ret != 0);
|
||||
// if this fails, no problem - we really only care if fs is FAT,
|
||||
// and will assume that's not the case (since fs_name != "FAT").
|
||||
|
@ -268,11 +268,13 @@ static void init_vkmap(SDLKey (&VK_keymap)[256])
|
||||
inline SDLKey vkmap(int vk)
|
||||
{
|
||||
static SDLKey VK_SDLKMap[256]; // VK_SDLKMap[vk] == SDLK
|
||||
|
||||
ONCE( init_vkmap(VK_SDLKMap); );
|
||||
|
||||
debug_assert(vk >= 0 && vk < 256);
|
||||
|
||||
if(!(0 <= vk && vk < 256))
|
||||
{
|
||||
debug_warn("vkmap: invalid vk");
|
||||
return SDLK_UNKNOWN;
|
||||
}
|
||||
return VK_SDLKMap[vk];
|
||||
}
|
||||
|
||||
@ -1010,28 +1012,25 @@ int SDL_SemWait(SDL_sem* sem)
|
||||
// threads
|
||||
//
|
||||
|
||||
|
||||
// users don't need to allocate SDL_Thread variables, so type = void
|
||||
// API returns SDL_Thread*, which is the HANDLE value itself.
|
||||
union pthread_sdl
|
||||
{
|
||||
pthread_t p;
|
||||
SDL_Thread* s;
|
||||
};
|
||||
//
|
||||
// we go through hoops to avoid type cast warnings;
|
||||
// a simple union { pthread_t; SDL_Thread* } yields "uninitialized"
|
||||
// warnings in VC2005, so we coerce values directly.
|
||||
cassert(sizeof(pthread_t) == sizeof(SDL_Thread*));
|
||||
|
||||
SDL_Thread* SDL_CreateThread(int(*func)(void*), void* param)
|
||||
{
|
||||
pthread_sdl u;
|
||||
if(pthread_create(&u.p, 0, (void*(*)(void*))func, param) < 0)
|
||||
pthread_t thread = 0;
|
||||
if(pthread_create(&thread, 0, (void*(*)(void*))func, param) < 0)
|
||||
return 0;
|
||||
return u.s; // TODO: uninitialised value?
|
||||
return *(SDL_Thread**)&thread;
|
||||
}
|
||||
|
||||
int SDL_KillThread(SDL_Thread* thread)
|
||||
{
|
||||
pthread_sdl u;
|
||||
u.s = thread;
|
||||
pthread_cancel(u.p);
|
||||
pthread_cancel(*(pthread_t*)&thread);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user