CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 16
  1. #1
    Join Date
    Jan 2007
    Posts
    8

    Question Constructors for global variables (objects) are not being called

    I have a VC++ project B that is linked into a static library "B.lib". This library is linked into project A which creates A.exe. The constructors for the global varaiables in B do not get called.

    1. If I have golbal variables in A then there is no problem - the constructors for those get called.

    2. I f the solution (Project A and B) get linked on my coleagues computer then there is no problem.
    3. The whole soltion is shared between us via rational clearcase so we have the same sources and the same project files.

    - so it must be one of the flags of visual studio - but which???
    Thanks,
    D.

  2. #2
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Constructors for global variables (objects) are not being called

    Quote Originally Posted by dannyg
    I have a VC++ project B that is linked into a static library "B.lib". This library is linked into project A which creates A.exe. The constructors for the global varaiables in B do not get called.
    You need to provide a little more information.

    Are your global variables reliant on other global variables to be constructed? In other words, does global A require global B to be fully constructed? If so, then there is no standard order of construction of these objects.

    If you mean that after main() is called, your global variables are not constructed, that's hard to believe, since after main() is called, globals should have been constructed. This is especially the case if the whole thing is a single executable (no external DLL's, EXE's or other modules have any role in the construction of the global variables).
    - so it must be one of the flags of visual studio - but which???
    If the problem is what I stated earlier, the easiest thing to do is redesign the program so it doesn't use globals and doesn't rely on one global constructing another global. Otherwise, you will have to produce a small example that shows a complete executable program that shows that the globals are not constructed after the main() entry point has been entered.

    Regards,

    Paul McKenzie

  3. #3
    Join Date
    May 2006
    Location
    Taiwan, Republic of China
    Posts
    126

    Re: Constructors for global variables (objects) are not being called

    Hi, dannyg:

    I suggest you to make a small B and A and try to use the smaller
    programs to reproduce the problem.
    If you can reproduce the problem and cannot figure out the solution,
    you can attached the smaller programs on this froum so that we can
    find out the problem more easily.

  4. #4
    Join Date
    Jan 2007
    Posts
    8

    Question Re: Constructors for global variables (objects) are not being called

    I tried reconstructing in a small example - but there is no problem there. The project where this happens I cant post here. Again it has to be some flag or bug - if anyone is aware of.

  5. #5
    Join Date
    Jan 2002
    Location
    Scaro, UK
    Posts
    5,940

    Re: Constructors for global variables (objects) are not being called

    I've come across this before.

    Static objects in libraries don't get constructed even when the c++ spec says they should be.

    Add a dummy method to the offending classes - i.e. a method which does nothing - and call it in the OnInitialise of your application class. This will ensure that they are constructed.

    Darwen.
    www.pinvoker.com - PInvoker - the .NET PInvoke Interface Exporter for C++ Dlls.

  6. #6
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Constructors for global variables (objects) are not being called

    Quote Originally Posted by dannyg
    I tried reconstructing in a small example - but there is no problem there. The project where this happens I cant post here. Again it has to be some flag or bug - if anyone is aware of.
    Again, if the issue is that you are initializing a global that relies on another global being initialized, and both globals are defined in two separate modules, then there is no bug. If this is the case, you are relying on unspecified behaviour.

    Global objects that rely on the construction of other global objects is only guaranteed if all the globals are in one module (then the order of initialization is done in the order in which they are declared). If the globals are in different modules, there is no specified order of initialization.

    Regards,

    Paul McKenzie

  7. #7
    Join Date
    Jan 2007
    Posts
    8

    Re: Constructors for global variables (objects) are not being called

    Darwen - Thanks - You have isolated the problem.

    However your solution is not helping me. The point is that the constructutor of those global object registers to the application that there is another class derived of some common abstract class in the application now. By adding a function to the main code I am defeating the purpose.

    The point is not to have to change "main" each time I add a new class to register - thats what the global constructors are for.

    I am attaching a small project where I reconstructed the problem - now that I know what it is

    The situation is really ugly:
    1. I add the dummy function and it solves the problem.
    2. I remove the dummy function and there is still no problem.
    3. I rebuild the solution and the problem comes back!!!!

  8. #8
    Join Date
    Jan 2007
    Posts
    8

    Re: Constructors for global variables (objects) are not being called

    I dont know if my attachemet went through - trying again
    Attached Files Attached Files

  9. #9
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Constructors for global variables (objects) are not being called

    Quote Originally Posted by dannyg
    Darwen - Thanks - You have isolated the problem.

    However your solution is not helping me. The point is that the constructutor of those global object registers to the application that there is another class derived of some common abstract class in the application now. By adding a function to the main code I am defeating the purpose.
    And I guess everything that I stated was not considered.

    You are attempting to come up with a solution to something that isn't specified by C++, and that is the order of static initialization. This is a well-known issue that has been discussed many times over. I can point you to the C++ specification that explicitly states this, if I'm not convincing.

    Unless there is a documented way in the compiler settings to initialize static members in a certain order, then there is no order specified order and it's time to rethink your design.

    Regards,

    Paul McKenzie

  10. #10
    Join Date
    Jan 2007
    Posts
    8

    Wink Re: Constructors for global variables (objects) are not being called

    Paul,
    I have been programming in C++ for almost 20 years on Unix. I just moved to VC++. There is nothing new in what I am doing. The first object that tries to register itself also creates the registery. There is no dependency or assumption on the order of static initialization.

    I m interested to know if anyone has heard of this problem or if there is a flag to overcome it.

    Regards,
    Danny

  11. #11
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Constructors for global variables (objects) are not being called

    Quote Originally Posted by dannyg
    Paul,
    I have been programming in C++ for almost 20 years on Unix. I just moved to VC++. There is nothing new in what I am doing.
    Then you've relied on unspecified behaviour. I don't know what else to tell you except you have been lucky it has worked -- up until now. BTW, the relevant section in the ANSI specification is 3.6.2 (Initialization of non-local objects).

    That section even states that an implementation may "dynamically" initialize the global variable on first use in main(), and all your main() function calls is "testit()".

    Maybe this can help you:

    http://www.cs.huji.ac.il/labs/parall...e/tic0112.html

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; January 2nd, 2007 at 06:23 PM.

  12. #12
    Join Date
    Jan 2007
    Posts
    8

    Re: Constructors for global variables (objects) are not being called

    Paul,
    1. In the article - the guy there says there is a way to overcome it (#3). I would say thats what I do. I dont think we need to dwell on initialization order anymore.

    2. The example I sent demonstrates the problem I have. Try the following. Make sure to use not only the code files but also the project files. a) Build it and see if XX is printed. b) Then uncomment testit in main and see if XX in printed. c) Then comment testit and see if it is printed. Then rebuild and again see if XX is printed.

    I am using visual studio 2003.
    What I saw:

    a) XX not printed.
    b) XX printed.
    c) XX printed.
    d) XX not printed.

  13. #13
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Constructors for global variables (objects) are not being called

    Quote Originally Posted by dannyg
    Paul,
    1. In the article - the guy there says there is a way to overcome it (#3). I would say thats what I do. I dont think we need to dwell on initialization order anymore.
    Then why are you having the problem? It must be for some reason. You think that your program is well-defined -- it isn't.

    What I'm saying is that what you are doing is unspecified by the C++ standard. It isn't a bug in Visual C++. I pointed you to the section in the standard (3.6.2 item 3 to be exact). It no longer is an issue with order of initialization, but when those global objects actually are initialized by the implementation.

    You are expecting those global objects declared in different translation units to be initialized, just because main() is called. This is not required by the standard. From 3.6.2, item 3:
    It is implementation defined whether or not the dynamic initialization (8.5, 9.4, 12.1, 12.6.1) of an object of namespace scope is done before the first statement of main. If the initialization is deferred to some point in time after the first statement of main, it shall occur before the first use of any function or object defined in the same translation unit as the object to be initialized.
    This is then followed by an example showing global objects, and then what the program is and is not guaranteed to happen successfully. Your testit() function is defined in the same translation unit as XX. Therefore it is guaranteed to be instantiated when you call testit(), otherwise it isn't guaranteed.

    Maybe this entire thread should be moved to the non-Visual C++ forum. Then others who concentrate more on the language elements, as opposed to the Visual C++ forum, will have input on this issue. Posters such as SuperKoko, Graham, or exterminator (and others) can chime in.
    2. The example I sent demonstrates the problem I have. Try the following. Make sure to use not only the code files but also the project files. a) Build it and see if XX is printed. b) Then uncomment testit in main and see if XX in printed. c) Then comment testit and see if it is printed. Then rebuild and again see if XX is printed.

    I am using visual studio 2003.
    What I saw:

    a) XX not printed.
    b) XX printed.
    c) XX printed.
    d) XX not printed.
    And this doesn't suggest unspecified behaviour, just like I've been (and the ANSI standard) have been stating? I took your project, and tried it both in Visual Studio 2005 and Visual Studio 2003 -- differing behaviour. The behaviour of VC 2003 matches exactly what is described in section 3.2.6 (3). Only when the testit() function was called was XX constructed.

    Regards,

    Paul McKenzie

  14. #14
    Join Date
    Jan 2007
    Posts
    8

    Re: Constructors for global variables (objects) are not being called

    Hi,
    Just thought I would post the right answer here:
    My mistake was that I tried to compile B as a library. The library linker is "lazy" and does not add module B into the compiled exe because its not referenced directly or indirectly from main. Its not an issue of global constructors at all. If I add module B directly as an object then it works.

    Why I would want to add a module that has no reference is a good question: thats where the global constructors come in.

    there is a linker flag in VC++ /OPT:NOREF that forces linking but it does not work and there is an open bug on this:

    https://connect.microsoft.com/feedba...1.0&siteid=210

    It becomes a methodology question now. On Unix - working with Makfiles, we did not create libraries when we workred as a team. In VC this seems to be the method of choice - but I am new to this so there may be another way to organize a project. The reason we dont want to share project files is similar to the reason you dont want to share makefiles on Unix. You want to own the build process of you component. I would be interested to know if there is a setting in VC++ that lets me keep my code as a bunch of objects rather than a library.

  15. #15
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Constructors for global variables (objects) are not being called

    The caveat is that the object must produce a side-effect in the constructor or destructor so that it isn't optimized away.

    Reading further into the ANSI spec, the link you have states this:
    3.7.1

    If an object of static storage duration has initialization or a destructor with side effects, it shall not be eliminated even if it appears to be unused, except that a class object or its copy may be eliminated as specified in 12.8.
    Section 12.8 is where it is discussed that a compiler can optimize away copy construction or assignment if it sees fit.

    Now, the definition of a side-effect is in 1.9
    Accessing an object designated by a volatile lvalue (3.10), modifying an object, calling a library I/O function, or calling a function that does any of those operations are all side effects, which are changes in the
    state of the execution environment. Evaluation of an expression might produce side effects.
    So if your class constructor or destructor does not do any of these things, the constructor may not be called implicitly for the global object. Then that is where 3.6.2 comes into play, where the constructor of the global will be guaranteed to be called if you call a function that is in the same translation unit as the global object.

    So considering this, your constructor calls cout(), which is a library I/O function. Therefore the executable should not have removed the global constructor of XX.

    Here is where I may disagree with the bug report (note that no one has addressed it, as far as I see): The example calls "DebugBreak". I don't know if this calls a library I/O function or not. If it doesn't, then I don't know if this reported bug is justified.

    Regards,

    Paul McKenzie

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured