Thread: Static member (map) / constructor initialisation problem

  1. #1
    Registered User
    Join Date
    Oct 2005
    Posts
    88

    Static member (map) / constructor initialisation problem

    I've had this problem before and managed to fix it, but an HD failure has me back stuck with probably the same problem, after I've forgotten the solution.

    What I wanted to know was whether static class variables (a static map is the one I'm having particular trouble with) are guaranteed to be initialised before a class constructor is called? I've learnt a fair bit about how static members work recently but I'm still utterly stuck here.

    I want to assign to a std::map<string,string>, which is a static member of, for example, class CLASS, but I can't for the life of me work out how to make it work during the construction of CLASS. After the contructor is finished, I have no problems with assigning, btw.

    After trawling Google I'm tempted to think that static variables can sometimes be initialised after the constructor is finished. Is that right? Like I said, I have sorted this out before, but now I think that it was just luck that the compiler organised initialisation differently before because I'm pretty sure that the code should work. By that, I mean that a super cut-down version of the solution (which I think is set out in the above link) works, but after adding a load of extra functionality - which should be insulated from the functions/variables causing this problem - it disintegrates.

    Does this ring a bell with anyone? God, I hope it does.

    Cheers

  2. #2
    Rabble Rouser Slacker's Avatar
    Join Date
    Dec 2005
    Posts
    116
    What I wanted to know was whether static class variables (a static map is the one I'm having particular trouble with) are guaranteed to be initialised before a class constructor is called?
    Yes. Can you post the code you're having trouble with or a cut down version of it that still has the same problem? I followed your link, but the only problem with the code was that you were trying to modify a string literal.

  3. #3
    Registered User
    Join Date
    Oct 2005
    Posts
    88
    Ok so that's one problem sorted, thanks Slacker. What do you mean about me modifying a string literal though? Where do I do that?

    I would post a simple version of my code but I haven't managed to simplify it (and keep the problem) yet. I've been rebuillding the class up from scratch to see where the problem lies and so far I haven't been able to replicate it. The full class is far too big to expect anyone to bother reading through so I won't bother.

    The thing is though, that I'm sure that this code worked when I archived it. It was only when I was left to start working on it again (after reinstalling MSVS and Windows) that I can't get it working - incidentally, the code that I posted in the link above actually works now, even though it definately didn't when I put it up here.

    What I'm really asking here is what restrictions there are on class-level static containers (like the std::map one)? As I understand it they can be modified by non-static functions; they persist throughout the running of the program (no matter how many instances of the class you have); they're initialised before the class constructor is called - no matter how big your class is (right?); they're initialised to the standard for the variable/container (like 0, "", or whatever); you can assign to them in the class constructor.

    That list is true for private and public class variables/containers isn't it? I've looked over my files so many times but I'm none the wiser (which is getting me a bit miffed).

  4. #4
    Rabble Rouser Slacker's Avatar
    Join Date
    Dec 2005
    Posts
    116
    >What do you mean about me modifying a string literal though? Where do I do that?
    In your "test" example:
    Code:
    c.save_param("bill=bob");
    This sends a string literal to CLASS::save_param. Then in save_param you do this:
    Code:
    char *v = strchr( _nvpair, '=' );
    v still points to a string literal at this point. Then shortly thereafter you do this:
    Code:
    v[0] = 0x00;
    Which is modifying the contents of a string literal, which is bad because string literals can be stored in read-only memory. That breaks your example program, and once you fix it everything works fine:
    Code:
    #include <iostream>
    #include <map>
    #include <string>
    
    class CLASS
    {
    public:
      static std::map<std::string, std::string> params;
      void	save_param( const char *_nvpair );
    };
    
    std::map<std::string, std::string> CLASS::params;
    
    void	CLASS::save_param( const char *_nvpair )
    {
      const char *n = _nvpair;
      const char *v = strchr( _nvpair, '=' );	// this points just before 'value' begins
    
      if( v != 0 ){
        std::string name(n, v - n);
        std::string value(v + 1);
        params[name] = value;			// assign to the map<>
      }
    }
    
    int main(void)
    {
      CLASS c;
    
      c.save_param("bill=bob");
      std::cout<< "bill = " << c.params["bill"] << std::endl;
      return 0;
    }

  5. #5
    Rabble Rouser Slacker's Avatar
    Join Date
    Dec 2005
    Posts
    116
    What I'm really asking here is what restrictions there are on class-level static containers (like the std::map one)? As I understand it they can be modified by non-static functions; they persist throughout the running of the program (no matter how many instances of the class you have); they're initialised before the class constructor is called - no matter how big your class is (right?); they're initialised to the standard for the variable/container (like 0, "", or whatever); you can assign to them in the class constructor.
    Yes, yes, yes, yes, and yes. Static containers are just like any other static data member. They're treated as non-local objects when it comes to storage, initialization, and destruction; in other words, they're basically global variables with access restrictions.

  6. #6
    Registered User
    Join Date
    Oct 2005
    Posts
    88
    Great, so at least I'm close. Thanks again Slacker.

    The only thing is, for some reason I can't get the containers std::map or std::vector to actually work in my proper class. In the one I'm building up it's working fine but in the 'full' class I'm still having no luck. I've raked through it so many times without being able to see where the difference lies with regards to the containers. I've even go so far as to rebuild part of the class by copy/pasting all the relevant functions and variables, but what doesn't work in the proper class works fine when I've copied it over to another file.

    I could just be in the wrong (and probably am) but could there be anything about implimenting class-level static containers that is different to implimenting class-level static ints, or char *s or even std::strings that I'm missing?

  7. #7
    Rabble Rouser Slacker's Avatar
    Join Date
    Dec 2005
    Posts
    116
    but could there be anything about implimenting class-level static containers that is different to implimenting class-level static ints, or char *s or even std::strings that I'm missing?
    Well, first, a std::string is a container, so if there's a problem with containers then I imagine any non-trivial class, and certainly std::string would have problems too. It sounds like something else is going wrong and you're trying to troubleshoot the wrong things. Can you paste your class that's giving you trouble? Just remove stuff that doesn't seem relevant until it's as small as possible and still has the problem. Chances are good that you can find the problem that way, but if you can't, at least the code will be short enough to post here.

  8. #8
    Registered User
    Join Date
    Oct 2005
    Posts
    88
    I actually went and cut and burned the class down, just to see what was wrong with it because it was starting to annoy me to the point of distraction. The class wasn't (really) to blame as it happens. Something cropped up which I didn't realise was a problem. It compiled fine and I couldn't find anything on Google that refered to this problem at all.

    I'd defined the CLASS pointer in my main.cpp file as a global object. Basically I had a line like:
    Code:
    CLASS *q = new CLASS;
    That was the problem. Instead I had to make the pointer global, but put the 'new' in the main block. So I ended up with something like:
    Code:
    #include <everything>
    CLASS *q;
    ...
    int main( void )
    {
        q = new CLASS;
        ...
        return 0;
    }
    That was monumentally annoying. At least that's something totally obscure that I know now.

    Thanks a lot for your help there Slacker: very much appreciated.

  9. #9
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Is there a reason you are using a pointer there? Why not use a simple object that you create locally in main?

    If you decide to stick with the dynamically allocated version using new, don't forget to delete it at the end t oensure all destructors are called for the class and its members.

  10. #10
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Actually, due to the lack of specification on the ordering of instantiation in different modules, it IS possible for a class instance to be created before its static members are initialized.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  2. TCP Header problem (error)
    By nasim751 in forum C Programming
    Replies: 1
    Last Post: 04-25-2008, 07:30 AM
  3. get keyboard and mouse events
    By ratte in forum Linux Programming
    Replies: 10
    Last Post: 11-17-2007, 05:42 PM
  4. Static member of a class
    By Gravedigga in forum C++ Programming
    Replies: 2
    Last Post: 08-15-2005, 03:54 AM
  5. Static members.....creating problem
    By CodeJerk in forum C++ Programming
    Replies: 1
    Last Post: 11-21-2002, 09:31 AM