static object never inits

This is a discussion on static object never inits within the C++ Programming forums, part of the General Programming Boards category; I have a number of static members of classes interacting. One of them never gets initialized. I am trying to ...

  1. #1
    Lode Runner
    Join Date
    May 2004
    Posts
    53

    static object never inits

    I have a number of static members of classes interacting. One of them never gets initialized.

    I am trying to implement an common interface for audio devices, whatever the API. I register all APIs with a manager class. Since API objects and the manager objects are singletons I use static objects.

    AudioDevice.h
    Code:
    class AudioDeviceAPI
    {
    public:
      virtual ~AudioDeviceAPI();
      
      virtual uint32 GetDeviceCount() const = 0;
      virtual AudioDevice* GetDevice(uint32 index) const = 0;
      
      void RegisterWithManager();
    protected:
      AudioDeviceAPI();
      String mName;
    };
    
    typedef std::map<String, AudioDeviceAPI*> APIMap;
    
    class AudioDeviceManager
    {
    public:
      static AudioDeviceManager& Get();
      ~AudioDeviceManager();
      
      uint32 GetDeviceCount() const;
      AudioDevice* GetDevice(uint32 DeviceIndex);
      
      
    protected:
      AudioDeviceManager();
      
      friend void AudioDeviceAPI::RegisterWithManager();
      void RegisterAPI(const String& rAPIName, AudioDeviceAPI* pAPI);
      APIMap mAPIs;
      
      int32 mDeviceCount;
      
      static AudioDeviceManager* gpManager;
    };
    AudioDevice.cpp
    Code:
    void AudioDeviceAPI::RegisterWithManager()
    {
      AudioDeviceManager::Get().RegisterAPI(mName, this);
    }
    
    AudioDeviceManager& AudioDeviceManager::Get()
    {
      if (!gpManager)
      {
        gpManager = new AudioDeviceManager();
      }
      return *gpManager;
    }
    
    void AudioDeviceManager::RegisterAPI(const String& rAPIName, AudioDeviceAPI* pAPI)
    {
      APIMap::const_iterator end = mAPIs.end();
      APIMap::const_iterator it = mAPIs.find(rAPIName);
      if (it != end)
      {
        delete it->second;
      }
      mAPIs[rAPIName] = pAPI;
    }
    
    
    AudioDeviceManager* AudioDeviceManager::gpManager = NULL;
    This is the (simplified) interface I use. The actual API implementations are subclasses of AudioDeviceAPI.

    For example:
    AudioDevice_DirectSound.cpp
    Code:
    /* definition of AudioDeviceAPI_DirectSound goes here */
    
    AudioDeviceAPI_DirectSound::AudioDeviceAPI_DirectSound()
    {
        mName = "DirectSound";
        RegisterWithManager();
    }
    
    static AudioDeviceAPI_DirectSound DirectSoundAPI;
    AudioDevice_ASIO.cpp
    Code:
    /* definition of AudioDeviceAPI_ASIO goes here */
    
    AudioDeviceAPI_ASIO::AudioDeviceAPI_ASIO()
    {
        mName = "ASIO";
        RegisterWithManager();
    }
    
    static AudioDeviceAPI_ASIO AsioAPI;
    The Problem: The static instance of AudioDeviceAPI_ASIO is initialized. The DirectSound one isn't... I first had to make the singleton pattern around the manager (with the NULL init, and static getter) to ensure that it would always be constructed before the AudioDeviceAPI instances. But the DirectSound API is just never instantiated. No cout, no breakpoint...

    I have found a workaround using a bogus function forcing instantiation, but I'd like to know why it doesn't work.

    Working with Visual Studio 2005, if that'll help.

  2. #2
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,048
    So you're saying that even though you have this line
    Code:
    static AudioDeviceAPI_DirectSound DirectSoundAPI;
    the constructor for AudioDeviceAPI_DirectSound is never called?

    That seems rather strange. Are you sure you're linking with that source file?

    FWIW: you have so many classes that start with "AudioDevice" that I'd consider making a namespace of the same name.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  3. #3
    Lode Runner
    Join Date
    May 2004
    Posts
    53
    Quote Originally Posted by dwks View Post
    So you're saying that even though you have this line
    Code:
    static AudioDeviceAPI_DirectSound DirectSoundAPI;
    the constructor for AudioDeviceAPI_DirectSound is never called?

    That seems rather strange. Are you sure you're linking with that source file?
    Yes, I am linking. Yes, it is very strange.

    There are no explicit calls to my global API objects. Could it be optimization that removes this instance ?

  4. #4
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,048
    If optimisation does remove that instance, it's a bad optimisation because it changes the behaviour of the program. You never know what the constructor that didn't get called might have done. Maybe, for example, that constructor might have printed something to the screen that you would then expect to see.

    I can only imagine that somehow you're not compiling the code correctly, especially since
    Code:
    static AudioDeviceAPI_ASIO AsioAPI;
    works (i.e., the constructor for that class is called) and AudioDeviceAPI_ASIO is very similar to AudioDeviceAPI_DirectSound, right?

    Are there any other differences between those two classes?
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  5. #5
    Lode Runner
    Join Date
    May 2004
    Posts
    53
    Quote Originally Posted by dwks View Post
    I can only imagine that somehow you're not compiling the code correctly, especially since
    Code:
    static AudioDeviceAPI_ASIO AsioAPI;
    works (i.e., the constructor for that class is called) and AudioDeviceAPI_ASIO is very similar to AudioDeviceAPI_DirectSound, right?

    Are there any other differences between those two classes?
    The only major difference is that AudioDevice_DirectSound.cpp contains a lot of Windows/DirectX includes and code which might influence the compilation in a way I haven't thought of.


    Also, if I add an explicit reference to AudioDeviceAPI_DirectSound, with a static getter for example, then everything functions as normal, but defeats the principle of having a general definition of interface with multiple hidden implementations...

  6. #6
    Lode Runner
    Join Date
    May 2004
    Posts
    53
    I got the answer:

    The declaration of DirectSoundApi is inside a static library, while AsioApi is in the current project. Since there is no explicit reference to DirectSoundApi, it is not linked.

    http://social.msdn.microsoft.com/For...2-a1a0da0fb783

    I'm now looking for a design pattern for self-registration of the implementations. Any ideas?

  7. #7
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,274
    If you're not calling the lib why SHOULD it get linked? The answer isn't to link in a bunch of stuff that never gets called, the answer is to CALL the stuff.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  8. #8
    Lode Runner
    Join Date
    May 2004
    Posts
    53
    It is called, but it isn't called explicitly.

    The different implementations call the manager to register themselves.
    And the manager accesses them agnostically, using the abstract interface.

    At that point, it's supposed to call the lib, but there's no way for the compiler to know it.


    On the subject of self-registering implementations, any clues ?

  9. #9
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,274
    Quote Originally Posted by krappa View Post
    It is called, but it isn't called explicitly.
    Just to get this straight, your modules contain static objects which, when constructed, call back into the main program to register the module in some way?

    It's just a weird model. The main program, not the modules, should be triggering registration. I understand that you're trying to avoid making the main program aware of the modules. And yet you are running into this issue, which is indicating a design problem.

    I've worked with lots of code that contains a main program and multiple abstract modules, statically linked. Ultimately it boils down to explicitly calling some initializer somewhere. There's not really much way around it. For instance look at the FreeType library in ftmodule.h

    You can at least isolate the library names to a single point like that, then forget about it.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  10. #10
    Lode Runner
    Join Date
    May 2004
    Posts
    53
    That's pretty much what I ended up doing.

    Still, If someone knows of a way to do this implicitly, let me know.

  11. #11
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,274
    Quote Originally Posted by krappa View Post
    That's pretty much what I ended up doing.

    Still, If someone knows of a way to do this implicitly, let me know.
    If there was a way, we would have mentioned it by now.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. seg fault at vectornew
    By tytelizgal in forum C Programming
    Replies: 2
    Last Post: 10-25-2008, 02:22 PM
  2. uploading file to http server via multipart form data
    By Dynamo in forum C++ Programming
    Replies: 1
    Last Post: 09-03-2008, 05:36 AM
  3. global and static object
    By George2 in forum Windows Programming
    Replies: 6
    Last Post: 04-09-2008, 07:51 AM
  4. Problem with a file parser.
    By Hulag in forum C++ Programming
    Replies: 7
    Last Post: 03-17-2005, 09:54 AM
  5. opengl program as win API menu item
    By SAMSAM in forum Game Programming
    Replies: 1
    Last Post: 03-03-2003, 07:48 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21