Fixed crash when exiting because Graphics and GraphicHash are freed before CPatchManager
The earlier fix in bos SVN trunk r9918 on 2010-07-02 does not work reliably with GCC 4.4.5; it seems std::map::~map does not bother marking the map as empty. Instead, rely on C++ constructing objects in the order of definition and destructing them in the opposite order. In DEBUG builds, also add assertions to catch any attempt to access Graphics or GraphicsHash before they are constructed or after they are destructed.
This commit is contained in:
parent
da3b369551
commit
c84ac83904
1 changed files with 49 additions and 2 deletions
|
@ -52,12 +52,47 @@
|
|||
-- Variables
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
static enum {
|
||||
ModuleNotInitialized,
|
||||
ModuleOK,
|
||||
ModuleDeinitialized
|
||||
} GraphicsState;
|
||||
|
||||
static int HashCount;
|
||||
|
||||
static std::map<std::string, CGraphic *> GraphicHash;
|
||||
|
||||
static std::list<CGraphic *> Graphics;
|
||||
|
||||
struct CGraphicsModule {
|
||||
CGraphicsModule() {
|
||||
GraphicsState = ModuleOK;
|
||||
}
|
||||
~CGraphicsModule() {
|
||||
GraphicsState = ModuleDeinitialized;
|
||||
}
|
||||
static void AssertOK() {
|
||||
#ifdef DEBUG
|
||||
switch (GraphicsState) {
|
||||
case ModuleNotInitialized:
|
||||
fprintf(stderr, "The graphics module hasn't yet been initialized\n");
|
||||
// Do not call ExitFatal, because that calls exit,
|
||||
// which might attempt to call destructors again.
|
||||
abort();
|
||||
case ModuleOK:
|
||||
break;
|
||||
case ModuleDeinitialized:
|
||||
fprintf(stderr, "The graphics module has already been deinitialized\n");
|
||||
abort();
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
#endif // DEBUG
|
||||
}
|
||||
};
|
||||
|
||||
static CGraphicsModule GraphicsModule;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Functions
|
||||
----------------------------------------------------------------------------*/
|
||||
|
@ -490,6 +525,8 @@ CGraphic *CGraphic::New(const std::string &file, int w, int h)
|
|||
return new CGraphic;
|
||||
}
|
||||
|
||||
CGraphicsModule::AssertOK();
|
||||
|
||||
CGraphic *g = GraphicHash[file];
|
||||
if (!g) {
|
||||
g = new CGraphic;
|
||||
|
@ -526,6 +563,8 @@ CPlayerColorGraphic *CPlayerColorGraphic::New(const std::string &file, int w, in
|
|||
return new CPlayerColorGraphic;
|
||||
}
|
||||
|
||||
CGraphicsModule::AssertOK();
|
||||
|
||||
CPlayerColorGraphic *g = dynamic_cast<CPlayerColorGraphic *>(GraphicHash[file]);
|
||||
if (!g) {
|
||||
g = new CPlayerColorGraphic;
|
||||
|
@ -558,6 +597,7 @@ CPlayerColorGraphic *CPlayerColorGraphic::New(const std::string &file, int w, in
|
|||
*/
|
||||
CGraphic *CGraphic::ForceNew(const std::string &file, int w, int h)
|
||||
{
|
||||
CGraphicsModule::AssertOK();
|
||||
CGraphic *g = new CGraphic;
|
||||
if (!g) {
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
|
@ -602,6 +642,7 @@ CGraphic *CGraphic::Clone() const
|
|||
*/
|
||||
CPlayerColorGraphic *CPlayerColorGraphic::ForceNew(const std::string &file, int w, int h)
|
||||
{
|
||||
CGraphicsModule::AssertOK();
|
||||
CPlayerColorGraphic *g = new CPlayerColorGraphic;
|
||||
if (!g) {
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
|
@ -654,6 +695,8 @@ void CGraphic::Load()
|
|||
return;
|
||||
}
|
||||
|
||||
CGraphicsModule::AssertOK();
|
||||
|
||||
// TODO: More formats?
|
||||
if (LoadGraphicPNG(this, false) == -1) {
|
||||
fprintf(stderr, "Can't load the graphic `%s'\n", File.c_str());
|
||||
|
@ -738,7 +781,7 @@ void CGraphic::Free(CGraphic *g)
|
|||
}
|
||||
}
|
||||
|
||||
if (!Graphics.empty()) {
|
||||
if (GraphicsState == ModuleOK) {
|
||||
Graphics.remove(g);
|
||||
}
|
||||
}
|
||||
|
@ -747,7 +790,7 @@ void CGraphic::Free(CGraphic *g)
|
|||
FreeSurface(&g->SurfaceFlip);
|
||||
|
||||
if (!g->HashFile.empty()) {
|
||||
if (!GraphicHash.empty()) {
|
||||
if (GraphicsState == ModuleOK) {
|
||||
GraphicHash.erase(g->HashFile);
|
||||
}
|
||||
}
|
||||
|
@ -760,6 +803,8 @@ void CGraphic::Free(CGraphic *g)
|
|||
*/
|
||||
void FreeOpenGLGraphics()
|
||||
{
|
||||
CGraphicsModule::AssertOK();
|
||||
|
||||
std::list<CGraphic *>::iterator i;
|
||||
for (i = Graphics.begin(); i != Graphics.end(); ++i) {
|
||||
if ((*i)->Textures) {
|
||||
|
@ -781,6 +826,7 @@ void FreeOpenGLGraphics()
|
|||
*/
|
||||
void ReloadGraphics()
|
||||
{
|
||||
CGraphicsModule::AssertOK();
|
||||
std::list<CGraphic *>::iterator i;
|
||||
for (i = Graphics.begin(); i != Graphics.end(); ++i) {
|
||||
if ((*i)->Textures) {
|
||||
|
@ -1326,6 +1372,7 @@ void CGraphic::MakeShadow()
|
|||
|
||||
void FreeGraphics()
|
||||
{
|
||||
CGraphicsModule::AssertOK();
|
||||
std::map<std::string, CGraphic *>::iterator i;
|
||||
while (!GraphicHash.empty()) {
|
||||
i = GraphicHash.begin();
|
||||
|
|
Loading…
Add table
Reference in a new issue