Okay, the responses *sorta* fixed the issue I've been having with the singleton. It doesn't crash anymore, but now there's something else going wrong. Whenever the singleton class actually gets used, it crashes, but somewhere else in the program (an internal crash within SDL_InitSubSystem(SDL_INIT_VIDEO)). And honestly, I have no idea what's going on here. Maybe I should have shared the debugging class while I was at it.
/******************************************************************************
Copyright (C) 1999, 2000 NVIDIA Corporation
This file is provided without support, instruction, or implied warranty of any
kind. NVIDIA makes no guarantee of its fitness for a particular purpose and is
not liable under any circumstances for any damages or loss whatsoever arising
from the use or inability to use this file or items derived from it.
Comments:
Simple debug support with stream input for complex arguments.
Also writes to a debug log style file.
Declare this somewhere in your .cpp file:
NVDebug dbg(DebugLevel, "outfile.txt")
// Output Like this
DISPDBG(0, "This" << " is " << "a useful debug class");
cmaughan@nvidia.com
******************************************************************************/
#ifndef __NVDEBUG_H
#define __NVDEBUG_H
#ifdef _WIN32
#include <windows.h>
#pragma warning(disable: 4786)
#include <tchar.h>
#endif
#pragma warning(disable: 4786)
#include <iostream>
#pragma warning(disable: 4786)
#include <sstream>
#pragma warning(disable: 4786)
#include <iomanip>
#pragma warning(disable: 4786)
#include <strstream>
#pragma warning(disable: 4786)
#include <fstream>
#pragma warning(disable: 4786)
#include <assert.h>
#include "singleton.h"
#ifdef _WIN32
#include <crtdbg.h>
#endif
/* Non-Windows platforms */
#ifndef _WIN32
#define OutputDebugString printf
#define TEXT(s) s
#endif
/* Trap functionality */
#ifdef _MSC_VER
#define __trap _asm int 3
#else
#define __tram __asm__("int $3")
#endif
static const DWORD MaxDebugFileSize = 100000;
class NVDebug : public Singleton<NVDebug>
{
public:
NVDebug(unsigned int GlobalDebugLevel, const char* pszFileName)
: m_GlobalDebugLevel(GlobalDebugLevel),
m_dbgLog(pszFileName, std::ios::out | std::ios::trunc) // Open a log file for debug messages
{
OutputDebugString(TEXT("NVDebug::NVDebug\n"));
}
virtual ~NVDebug()
{
m_dbgLog.flush();
m_dbgLog.close();
m_strStream.flush();
m_strStream.clear();
}
// Flush the current output
#ifdef _WIN32
void NVDebug::EndOutput()
#else
void EndOutput()
#endif
{
m_strStream << std::endl << std::ends;
// Don't make a huge debug file.
if (m_dbgLog.tellp() < MaxDebugFileSize)
{
m_dbgLog << m_strStream.str();
FlushLog();
}
OutputDebugString(m_strStream.str());
m_strStream.freeze(false);
m_strStream.seekp(0);
}
unsigned int GetLevel() const { return m_GlobalDebugLevel; };
std::ostrstream& GetStream() { return m_strStream; }
void FlushLog() { m_dbgLog.flush(); }
private:
std::ostrstream m_strStream;
std::ofstream m_dbgLog;
unsigned int m_GlobalDebugLevel;
};
#ifdef _DEBUG
#define DISPDBG(a, b) \
do \
{ \
if (NVDebug::GetSingletonPtr() != NULL) \
if (a <= NVDebug::GetSingleton().GetLevel()) { \
NVDebug::GetSingleton().GetStream() << b; \
NVDebug::GetSingleton().EndOutput(); } \
} while(0)
#define NVASSERT(a, b) \
do \
{ \
static bool bIgnore = false; \
if (!bIgnore && ((int)(a) == 0)) \
{ \
std::ostringstream strOut; \
strOut << b << "\nAt: " << __FILE__ << ", " << __LINE__; \
int Ret = MessageBoxEx(NULL, strOut.str().c_str(), "NVASSERT", MB_ABORTRETRYIGNORE, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT )); \
if (Ret == IDIGNORE) \
{ \
bIgnore = true; \
} \
else if (Ret == IDABORT) \
{ \
__trap; \
} \
} \
} while (0)
#else
#define DISPDBG(a, b)
#define NVASSERT(a, b)
#endif
// Note that the cast ensures that the stream
// doesn't try to interpret pointers to objects in different ways.
// All we want is the object's address in memory.
#define BASE_DBG_PTR(a) \
"0x" << std::hex << (DWORD)(a) << std::dec
#endif // __NVDEBUG_H
I hacked it up a bit so it would compile under XCode (and yeah, I know I still have to deal with the MessageBox code; SDL has a rough equivalent), and so far, I've only used the example from the top comment in this header. The code works, and the string is placed in the log file, but after that, that totally unrelated crash happens shortly after. Doesn't make any sense to me, or was a pointer corrupted somehow? I dunno what this singleton class is actually doing, or even what makes it useful. Any more ideas? Thanks.
Shogun.
EDIT: I forgot to mention that if I comment out DISPDBG in my code, no crashes.
//DISPDBG(0, "This" << " is " << "a useful debug class"); <- No crash