# This singleton keeps crashing.

## Recommended Posts

blueshogun96    2264

I'm not an expert on singletons, and I only have one bit of code that uses it.  It's part of a debugging system from one of NVIDIA's SDKs, and I find  their code to be useful in my engine.  Now, this singleton class works fine in Windows, but not for UNIX based OSes like MacOSX.  This is what it looks like:

#include <cassert>

template <typename T> class Singleton
{
static T* ms_Singleton;

public:
Singleton( void )
{
assert( !ms_Singleton );
int offset = *(int*)(T*)1 - *(int*)(Singleton <T>*)(T*)1;
ms_Singleton = (T*)(*(int*)this + offset);
}
virtual ~Singleton( void )
{  assert( ms_Singleton );  ms_Singleton = 0;  }
static T& GetSingleton( void )
{  assert( ms_Singleton );  return ( *ms_Singleton );  }
static T* GetSingletonPtr( void )
{  return ( ms_Singleton );  }
};

template <typename T> T* Singleton <T>::ms_Singleton = 0;


So, it crashes in the constructor, starting at the second line.  The windows version had (int) instead of *(int*).  I just changed that so XCode would stop complaining about it.  It could be something simple.  Right now, I'm so tired, I can barely stay awake.  So, I was hoping someone who isn't as braindead as I am right now could point me in the right direction.  Thanks.

Shogun.

##### Share on other sites
Auskennfuchs    1032

This *(int*) doesnt work in my opinion, because you subtract the content of the adresses instead of subtract the addresses of the pointers. This little piece of code should just calculates the offset from the Singleton class to the covered class. So in memorylayout the ms_Singleton-member needs its 4 or 8 byte for its pointer-storage. Appended to ms_Singleton the covered-class members are aligned. So to get the right startposition when GetSingleton is used, the pointer is shifted by the calculated offset. Afaik this code was a workaround for older compilers and the newer ones automatically calculate those pointer-shiftings. I would give it a try to just cast the pointer ms_Singleton = (T*)this;

In VS2013 it should probably work, but I haven't tried it on Linux or Mac.

Btw. using int as datatype is critical, because it's size isn't constant through x86 and x64 and different OS. You should use char, short or long.

##### Share on other sites

Btw. using int as datatype is critical, because it's size isn't constant through x86 and x64 and different OS. You should use char, short or long.

If you needed fixed sizes for your datatypes use stdint.h this header file should be part of the compiler and works in respect to the pre defined macros a compiler issues. The headerfile defines types like int16_t uint32_t and so on. The usage of these types guarantee that the variables/attributes are always the expected size regardless you compile for 32 or 64 bit OS.

Only for MS development environments this headerfile was not part of developerstudio. But because I did not use them for a long time it may changed since my last try. But somewhere in the internet you will even find a MS compatible version of stdint.h

##### Share on other sites
Hodgman    51224
Yeah, the standard type for an integer that's big enough to store the difference between two pointers, is ptrdiff_t

Only for MS development environments this headerfile was not part of developerstudio. But because I did not use them for a long time it may changed since my last try. But somewhere in the internet you will even find a MS compatible version of stdint.h

recent versions of MSVC include stdint.h, it's only missing in older versions :D

##### Share on other sites
BitMaster    8651

If you needed fixed sizes for your datatypes use stdint.h [...]

Yes, but if at all possible you should use <cstdint>. Unlike <stdint.h> which might be there or might not be there, <cstdint> is part of the standard library (since C++11).

##### Share on other sites
Wooh    1088
&amp;nbsp;

If you needed fixed sizes for your datatypes use stdint.h [...]

Yes, but if at all possible you should use &amp;lt;cstdint&amp;gt;. Unlike &amp;lt;stdint.h&amp;gt; which might be there or might not be there, &amp;lt;cstdint&amp;gt; is part of the standard library (since C++11).
stdint.h is in C++11 too, but I agree with you that cstdint should be preferred.

##### Share on other sites
BitMaster    8651
<stdint.h> is part of the C standard library, not the C++ standard library. While most compilers allow you to include their C includes from C++, they are not required to do so (nor do they even have to have C includes somewhere to be standard compliant).

##### Share on other sites

Anyways where it is. The types defined there are to avoid troubles with the data sizes if something, hardware, depends on it.

##### Share on other sites
Gohliath    348

may help

http://scottbilas.com/publications/gem-singleton/

a little description of that singleton

that version got updated already and replaced

Singleton( void )
{
assert(!ms_singleton);
int offset = (int)(T*)1 - (int)(Singleton *)(T*)1;
ms_singleton = (T*)((int)this + offset);
}

with

Singleton( void )
{
assert( !ms_singleton );
ms_singleton = static_cast <T*> (this);
}

##### Share on other sites
Wooh    1088

<stdint.h> is part of the C standard library, not the C++ standard library. While most compilers allow you to include their C includes from C++, they are not required to do so (nor do they even have to have C includes somewhere to be standard compliant).

This is what the C++11 standard (Appendix D.5) says about it.

For compatibility with the C standard library and the C Unicode TR, the C++ standard library provides the 25 C headers, as shown in Table 154.

##### Share on other sites
BitMaster    8651
I concede the point, but I would still strongly recommend never to include C headers instead of their C++ counterpart unless an extremely compelling reason exists. Edited by BitMaster

##### Share on other sites
blueshogun96    2264

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.

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
#endif