static initialization access violation error

Discussion in 'C++' started by marvind, Jul 12, 2005.

  1. marvind

    marvind Guest

    I think I am running into the static initialization problem but I do
    not understand why.

    I am trying to parse a configuration file. To make this parser generic
    I register callbacks for various section keywords in the configuration
    file. I want to share this map of callbacks across multiple instances
    of the config file (for example, when I merge two files). Whenever I
    introduce a new section in the configuration file, I define a new class
    for this section and also register the new callback for this section
    with a new keyword.

    I get an access violation exception when I step through this code and I
    see the callback map Root() is uninitialized. Since I am trying to
    populate the callback map only after constructing an instance of the
    configuration class, why is the static callback map still
    uninitialized?

    Below is the basic code structure:

    -- In CConfig.h
    class CConfig
    {
    public:
    ...
    // Note that Register is not a static function
    bool Register(const std::string& skey, CallbackFn callback);
    private:
    // want to share this map across all instances
    static std::map<std::string, CallbackFn> s_callbacks;
    };


    -- In CCMA.h
    class CCMA : public CSection
    {
    ...
    };

    -- In CCMA.cpp
    // anonymous namespace
    namespace
    {
    // ReadCMA -> new CCMA and then read relevant tags from config file
    bool bRegisterCMA = G_CONFIG.Register("CMA_START", ReadCMA);
    };

    G_CONFIG returns either existing global pointer to CConfig after
    creating a new CConfig object if necessary simulating singleton
    behavior. However, we sometimes need more than one instance of CConfig
    for example to merge entries from 2 different configuration files and
    so we access these without using G_CONFIG (I still want to share the
    callback map).

    Thanks
     
    marvind, Jul 12, 2005
    #1
    1. Advertising

  2. marvind

    Paul Groke Guest

    marvind wrote:
    > I think I am running into the static initialization problem but I do
    > not understand why.
    >
    > I am trying to parse a configuration file. To make this parser generic
    > I register callbacks for various section keywords in the configuration
    > file. I want to share this map of callbacks across multiple instances
    > of the config file (for example, when I merge two files). Whenever I
    > introduce a new section in the configuration file, I define a new class
    > for this section and also register the new callback for this section
    > with a new keyword.
    >
    > I get an access violation exception when I step through this code and I
    > see the callback map Root() is uninitialized. Since I am trying to
    > populate the callback map only after constructing an instance of the
    > configuration class, why is the static callback map still
    > uninitialized?
    >
    > Below is the basic code structure:
    >
    > -- In CConfig.h
    > class CConfig
    > {
    > public:
    > ...
    > // Note that Register is not a static function
    > bool Register(const std::string& skey, CallbackFn callback);
    > private:
    > // want to share this map across all instances
    > static std::map<std::string, CallbackFn> s_callbacks;
    > };
    >
    >
    > -- In CCMA.h
    > class CCMA : public CSection
    > {
    > ...
    > };
    >
    > -- In CCMA.cpp
    > // anonymous namespace
    > namespace
    > {
    > // ReadCMA -> new CCMA and then read relevant tags from config file
    > bool bRegisterCMA = G_CONFIG.Register("CMA_START", ReadCMA);
    > };
    >
    > G_CONFIG returns either existing global pointer to CConfig after
    > creating a new CConfig object if necessary simulating singleton
    > behavior. However, we sometimes need more than one instance of CConfig
    > for example to merge entries from 2 different configuration files and
    > so we access these without using G_CONFIG (I still want to share the
    > callback map).
    >
    > Thanks
    >


    You need to make sure that "s_callbacks" is initialized before
    "bRegisterCMA" is. One way to do so would be to grab a proper
    Sincleton implementation, and make "s_callbacks" a singleto too.
    The simple solution for single-threaded programs is to put all your
    static data in functions that return references to the data. That way
    you make sure that they are constructed in the right order.

    And: you get the problem because "s_callbacks" is not initialized with
    the first instance of the class, but along with all other static data.
    Nonconst static members are just "globals in a namespace".
     
    Paul Groke, Jul 13, 2005
    #2
    1. Advertising

  3. marvind

    marvind Guest

    Thank you for your response.

    I wrapped the callback map as you suggested:
    stlCallbackMap& CallbackMap()
    {
    static stlCallbackMap callbackMap;
    return callbackMap;
    }

    That "seems" to work. My mistake was that I thought that static data
    members of a class are initialized before the first instance of the
    class is constructed, instead of the runtime treating them as just
    globals in a namespace.

    Are there good "free" tools that I can use to find out if there are
    such errors in the code since these errors depend on how the files are
    compiled?
     
    marvind, Jul 13, 2005
    #3
  4. marvind

    Howard Guest

    "marvind" <> wrote in message
    news:...
    >I think I am running into the static initialization problem but I do
    > not understand why.
    >
    > I am trying to parse a configuration file. To make this parser generic
    > I register callbacks for various section keywords in the configuration
    > file. I want to share this map of callbacks across multiple instances
    > of the config file (for example, when I merge two files). Whenever I
    > introduce a new section in the configuration file, I define a new class
    > for this section and also register the new callback for this section
    > with a new keyword.
    >
    > I get an access violation exception when I step through this code and I
    > see the callback map Root() is uninitialized. Since I am trying to
    > populate the callback map only after constructing an instance of the
    > configuration class, why is the static callback map still
    > uninitialized?
    >


    What's "Root()"???

    > Below is the basic code structure:
    >
    > -- In CConfig.h
    > class CConfig
    > {
    > public:
    > ...
    > // Note that Register is not a static function
    > bool Register(const std::string& skey, CallbackFn callback);
    > private:
    > // want to share this map across all instances
    > static std::map<std::string, CallbackFn> s_callbacks;
    > };
    >
    >
    > -- In CCMA.h
    > class CCMA : public CSection
    > {
    > ...
    > };
    >
    > -- In CCMA.cpp
    > // anonymous namespace
    > namespace
    > {
    > // ReadCMA -> new CCMA and then read relevant tags from config file
    > bool bRegisterCMA = G_CONFIG.Register("CMA_START", ReadCMA);
    > };
    >
    > G_CONFIG returns either existing global pointer to CConfig after
    > creating a new CConfig object if necessary simulating singleton
    > behavior. However, we sometimes need more than one instance of CConfig
    > for example to merge entries from 2 different configuration files and
    > so we access these without using G_CONFIG (I still want to share the
    > callback map).
    >
    > Thanks
    >



    You're assuming that s_callbacks is initialized when the first instance of
    the class is created. That's not the case. You need to initialize it
    yourself somewhere. That can be done in the manner of a Singleton (inside
    an accessor function), or at the global level (outside the class in your
    implementation file).

    -Howard
     
    Howard, Jul 13, 2005
    #4
  5. marvind

    Paul Groke Guest

    marvind wrote:
    > Thank you for your response.
    >
    > I wrapped the callback map as you suggested:
    > stlCallbackMap& CallbackMap()
    > {
    > static stlCallbackMap callbackMap;
    > return callbackMap;
    > }
    >
    > That "seems" to work. My mistake was that I thought that static data
    > members of a class are initialized before the first instance of the
    > class is constructed, instead of the runtime treating them as just
    > globals in a namespace.
    >
    > Are there good "free" tools that I can use to find out if there are
    > such errors in the code since these errors depend on how the files are
    > compiled?


    If it depends on how it's compiled, then it's an error - whether it
    shows or not.
    As for tools: asserts, logs, traces. Other than that I don't know
    free tools - though they might probably exist. In my company we
    use MSVC7.1 which happens to have an excellent debugger, and for
    real tough cases we use Bounds-Checker and/or VTune (profiling).

    You might ask in a group/forum specific to whatever OS/compiler
    you are using.
     
    Paul Groke, Jul 14, 2005
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Boogie El Aceitoso
    Replies:
    5
    Views:
    473
    Josh Sebastian
    Oct 1, 2003
  2. muser

    Access violation error

    muser, Oct 27, 2003, in forum: C++
    Replies:
    10
    Views:
    616
    lilburne
    Nov 7, 2003
  3. JKop
    Replies:
    10
    Views:
    950
  4. woyt.a
    Replies:
    11
    Views:
    303
    Öö Tiib
    Feb 11, 2013
  5. HighBeliever
    Replies:
    0
    Views:
    101
    HighBeliever
    Jul 4, 2013
Loading...

Share This Page