1
0
forked from mirrors/0ad

fix: avoid reentering allocation hook if an error is raised within memory allocators

This was SVN commit r6196.
This commit is contained in:
janwas
2008-07-04 18:02:54 +00:00
parent b46f8b9ed8
commit 5b757e536f
+34 -14
View File
@@ -1238,28 +1238,48 @@ static LibError dump_sym_function_type(DWORD UNUSED(type_id), const u8* p, DumpS
// clutter a bit and prevents infinite recursion for cyclical references
// (e.g. via struct S { S* p; } s; s.p = &s;)
typedef std::set<const u8*> PtrSet;
static PtrSet* already_visited_ptrs;
// allocated on-demand by ptr_already_visited. this cannot be a NLSO
// because it may be used before _cinit.
// if we put it in a function, construction still fails on VC7 because
// the atexit table will not have been initialized yet.
// note: allocating memory dynamically would cause trouble if dumping
// the stack from within memory-related code (the allocation hook would
// be reentered, which is not permissible).
static const size_t maxVisited = 1000;
static const u8* visited[maxVisited];
static size_t numVisited;
// called by debug_dump_stack but not during shutdown (this must remain valid
// until the very end to allow crash reports)
static void ptr_reset_visited()
{
delete already_visited_ptrs;
already_visited_ptrs = 0;
numVisited = 0;
}
static bool ptr_already_visited(const u8* p)
{
if(!already_visited_ptrs)
already_visited_ptrs = new PtrSet;
for(size_t i = 0; i < numVisited; i++)
{
if(visited[i] == p)
return true;
}
std::pair<PtrSet::iterator, bool> ret = already_visited_ptrs->insert(p);
return !ret.second;
if(numVisited < maxVisited)
{
visited[numVisited] = p;
numVisited++;
}
// capacity exceeded
else
{
// warn user - but only once (we can't use the regular
// debug_display_error and wdbg_assert doesn't have a
// suppress mechanism)
static bool haveComplained;
if(!haveComplained)
{
debug_printf("WARNING: ptr_already_visited: capacity exceeded, increase maxVisited\n");
debug_break();
haveComplained = true;
}
}
return false;
}