why static variables used in EXE and DLL are different?

Discussion in 'C++' started by Allen, Dec 12, 2006.

  1. Allen

    Allen Guest

    In a static library, there is a static variable definition.

    static CLogger::mapFile;

    In both EXE and DLL, I use the same code. CLogReader uses
    CLogger::mapFile to do some work.
    CLogReader logReader;

    But the result is different.

    When used in EXE, mapFile constructor is not called? (Why?). See EXE
    log below.

    Creating map file 0x00499f90 (call CMapFile constructor)
    Enter CLogReader now ...
    GetMapFile 0x00499f90 ... (return the static mapFile)
    Exit CLogReader now ...

    When used in DLL, mapFile constructor is called, but after the first
    use. See DLL log below

    Enter CLogReader ...
    GetMapFile 0x10025830 ... (return the static mapFile)
    Exit CLogReader ...
    Creating map file 0x10025830 (in CMapFile constructor)

    It is too strange to understand. Why???
     
    Allen, Dec 12, 2006
    #1
    1. Advertising

  2. Allen wrote:
    > In a static library, there is a static variable definition.

    ....
    > It is too strange to understand. Why???


    Do you have a small code sample that exhibits this behaviour ?
     
    Gianni Mariani, Dec 12, 2006
    #2
    1. Advertising

  3. Allen

    Ian Collins Guest

    Allen wrote:
    > In a static library, there is a static variable definition.
    >
    > static CLogger::mapFile;
    >
    > In both EXE and DLL, I use the same code. CLogReader uses
    > CLogger::mapFile to do some work.


    Off topic here, try a windows programming group.

    --
    Ian Collins.
     
    Ian Collins, Dec 12, 2006
    #3
  4. Allen

    F.J.K. Guest

    Allen schrieb:

    > In a static library, there is a static variable definition.
    >
    > static CLogger::mapFile;
    >
    > In both EXE and DLL, I use the same code. CLogReader uses
    > CLogger::mapFile to do some work.
    > CLogReader logReader;
    >
    > But the result is different.
    >
    > When used in EXE, mapFile constructor is not called? (Why?). See EXE
    > log below.
    >
    > Creating map file 0x00499f90 (call CMapFile constructor)
    > Enter CLogReader now ...
    > GetMapFile 0x00499f90 ... (return the static mapFile)
    > Exit CLogReader now ...
    >
    > When used in DLL, mapFile constructor is called, but after the first
    > use. See DLL log below
    >
    > Enter CLogReader ...
    > GetMapFile 0x10025830 ... (return the static mapFile)
    > Exit CLogReader ...
    > Creating map file 0x10025830 (in CMapFile constructor)
    >
    > It is too strange to understand. Why???


    Well, the following is a wild guess only, try to follow the guidelines
    for posting on this newsgroup for better answers next time, (esp.
    http://www.parashift.com/c -faq-lite/how-to-post.html#faq-5.8)

    It seems you have used two static variables of type CLogReader and
    CMapFile and rely on the order of their initialization (you probably
    want CMapFile initialized before CLogReader). This is a mistake on your
    side, as C++ explicitly states, that no guarantee is given, which
    constructor will be called first. Out of my head I'd propose one of the
    following resolutions.

    a) use local variables instead of globals and pass around
    references/pointers. The order of initialization for local variables is
    guaranteed.
    b) use only ONE static object which agglomerates dependent objects,
    like

    class CLogReaderWithCMapFile {
    CMapFile mapFile;
    CLogReader logReader;
    ...
    }

    Here you have complete control over the order of initialization in
    your constructor.

    CLogReaderWithCMapfile (...):
    mapFile (...),
    logReader (...)
    {
    }

    Btw, there's undoubtedly people who are going to tell you this is
    off-topic, as it is MS specific. Just ignore them, that's just typical
    "background noise" whenever people can tell, you are using MS products
    (from the name of your dynamic library, .dll instead of .so). What has
    hit you is a classical case of so called "undefined behaviour" in C++,
    something totally on topic for this newsgroup ;-)
     
    F.J.K., Dec 12, 2006
    #4
  5. Allen

    Lionel B Guest

    On Tue, 12 Dec 2006 04:33:58 -0800, F.J.K. wrote:

    > Allen schrieb:
    >
    >> In a static library, there is a static variable definition.
    >>
    >> static CLogger::mapFile;
    >>
    >> In both EXE and DLL, I use the same code. CLogReader uses
    >> CLogger::mapFile to do some work.
    >> CLogReader logReader;
    >>
    >> But the result is different.
    >>
    >> [snip]

    >
    > Btw, there's undoubtedly people who are going to tell you this is
    > off-topic, as it is MS specific.


    How do we know it *isn't* MS specific since insufficient code was posted?
    You yourself admit to making a "wild guess" (albeit quite likely a correct
    one).

    > Just ignore them, that's just typical "background noise" whenever people
    > can tell, you are using MS products (from the name of your
    > dynamic library, .dll instead of .so).


    Nonsense. You may well get (justifiable) complaints if your question is
    evidently MS-specific, or Linux-specific, or
    whatever non-C++-language-specific. If your query is on-topic nobody cares
    what products you're using.

    > What has hit you is a classical case of so called "undefined behaviour"
    > in C++, something totally on topic for this newsgroup ;-)


    ....or maybe it's something MS-specific ;-)

    --
    Lionel B
     
    Lionel B, Dec 12, 2006
    #5
  6. Allen

    Allen Guest


    > Well, the following is a wild guess only, try to follow the guidelines
    > for posting on this newsgroup for better answers next time, (esp.
    > http://www.parashift.com/c -faq-lite/how-to-post.html#faq-5.8)
    >
    > It seems you have used two static variables of type CLogReader and
    > CMapFile and rely on the order of their initialization (you probably
    > want CMapFile initialized before CLogReader). This is a mistake on your
    > side, as C++ explicitly states, that no guarantee is given, which
    > constructor will be called first. Out of my head I'd propose one of the
    > following resolutions.
    >
    > a) use local variables instead of globals and pass around
    > references/pointers. The order of initialization for local variables is
    > guaranteed.
    > b) use only ONE static object which agglomerates dependent objects,
    > like
    >
    > class CLogReaderWithCMapFile {
    > CMapFile mapFile;
    > CLogReader logReader;
    > ...
    > }
    >
    > Here you have complete control over the order of initialization in
    > your constructor.
    >
    > CLogReaderWithCMapfile (...):
    > mapFile (...),
    > logReader (...)
    > {
    > }
    >



    Yes. You are right. I cannot be sure that it is the right answer. But
    it works. Thank you!
    After I post this topic, I kept testing on this question. Now I find
    out a solution.

    In the .dll implementation, as you said, I used a global variable
    CLogReader. It is the point. Now I changed it to be a local static
    variable and a global pointer to solve the problem Below is the sample
    codes.

    /// previous version
    CLogReader logReader;

    DLL_EXPORT void InitLogReader()
    {
    logReader.InitLogReader();
    }

    DLL_EXPORT void ReadMesg()
    {
    logReader.ReadMesg();
    }

    /// corrected version
    CLogReader* pLogReader = NULL;

    DLL_EXPORT void InitLogReader()
    {
    static CLogReader logReader;
    logReader.InitLogReader();

    pLogReader = &logReader;
    }

    DLL_EXPORT void ReadMesg()
    {
    if (pLogReader == NULL)
    {
    printf("\nLogReader is not initialized");
    return;
    }
    pLogReader->ReadMesg();
    }

    I think it is not easy to give the anwser to this question. Thank you
    again.
     
    Allen, Dec 13, 2006
    #6
  7. Allen

    Madkour Guest

    Hi Allen,
    I think the reason for this strange behaviour is caused by the way the
    OS handles dlls and exes.
    dll's are better for performance since they are initialized and
    instantiated once (during their first call) and continue to operate to
    serve all client programmes. Only one copy of the dll is running at any
    one time. Exe's however, are treated just as any other programme is. A
    fresh copy is instantiated in a separate memory space every time it's
    required. This obviously has performance overhead.

    So, if the constructor is called only the very first time the programme
    is run, it will only run once in the case of a dll (that is when the
    dll is called for the first time) and will be called every time the exe
    is called (since a fresh copy of the exe will be created every time
    it's needed).

    In all fairness, I think this is more of a windows programming issue!
    :eek:)

    Cheers,
    Madkour


    Allen wrote:

    > > Well, the following is a wild guess only, try to follow the guidelines
    > > for posting on this newsgroup for better answers next time, (esp.
    > > http://www.parashift.com/c -faq-lite/how-to-post.html#faq-5.8)
    > >
    > > It seems you have used two static variables of type CLogReader and
    > > CMapFile and rely on the order of their initialization (you probably
    > > want CMapFile initialized before CLogReader). This is a mistake on your
    > > side, as C++ explicitly states, that no guarantee is given, which
    > > constructor will be called first. Out of my head I'd propose one of the
    > > following resolutions.
    > >
    > > a) use local variables instead of globals and pass around
    > > references/pointers. The order of initialization for local variables is
    > > guaranteed.
    > > b) use only ONE static object which agglomerates dependent objects,
    > > like
    > >
    > > class CLogReaderWithCMapFile {
    > > CMapFile mapFile;
    > > CLogReader logReader;
    > > ...
    > > }
    > >
    > > Here you have complete control over the order of initialization in
    > > your constructor.
    > >
    > > CLogReaderWithCMapfile (...):
    > > mapFile (...),
    > > logReader (...)
    > > {
    > > }
    > >

    >
    >
    > Yes. You are right. I cannot be sure that it is the right answer. But
    > it works. Thank you!
    > After I post this topic, I kept testing on this question. Now I find
    > out a solution.
    >
    > In the .dll implementation, as you said, I used a global variable
    > CLogReader. It is the point. Now I changed it to be a local static
    > variable and a global pointer to solve the problem Below is the sample
    > codes.
    >
    > /// previous version
    > CLogReader logReader;
    >
    > DLL_EXPORT void InitLogReader()
    > {
    > logReader.InitLogReader();
    > }
    >
    > DLL_EXPORT void ReadMesg()
    > {
    > logReader.ReadMesg();
    > }
    >
    > /// corrected version
    > CLogReader* pLogReader = NULL;
    >
    > DLL_EXPORT void InitLogReader()
    > {
    > static CLogReader logReader;
    > logReader.InitLogReader();
    >
    > pLogReader = &logReader;
    > }
    >
    > DLL_EXPORT void ReadMesg()
    > {
    > if (pLogReader == NULL)
    > {
    > printf("\nLogReader is not initialized");
    > return;
    > }
    > pLogReader->ReadMesg();
    > }
    >
    > I think it is not easy to give the anwser to this question. Thank you
    > again.
     
    Madkour, Dec 13, 2006
    #7
  8. Allen

    F.J.K. Guest

    Lionel B schrieb:

    > How do we know it *isn't* MS specific since insufficient code was posted?
    > You yourself admit to making a "wild guess" (albeit quite likely a correct
    > one).


    Well, there wasn't enough code posted to be sure either way. However,
    some guesses are "wilder" than others ;-) The OP was relying on order
    of initializations. Order of constructor calls for global objects is a
    pretty common pitfall of the language.

    >
    > > Just ignore them, that's just typical "background noise" whenever people
    > > can tell, you are using MS products (from the name of your


    > ...or maybe it's something MS-specific ;-)


    To be honest, there probably will be some kind of "MS-specificity" to
    the problem. Linking is notoriously underdefined by language
    standards, you've got no chance to keep this area free of platform
    specific information. But that's a problem of C++, too.
     
    F.J.K., Dec 13, 2006
    #8
  9. Allen

    Lionel B Guest

    On Wed, 13 Dec 2006 07:56:24 -0800, F.J.K. wrote:

    > Lionel B schrieb:
    >
    >> How do we know it *isn't* MS specific since insufficient code was posted?
    >> You yourself admit to making a "wild guess" (albeit quite likely a correct
    >> one).

    >
    > Well, there wasn't enough code posted to be sure either way. However,
    > some guesses are "wilder" than others ;-) The OP was relying on order
    > of initializations. Order of constructor calls for global objects is a
    > pretty common pitfall of the language.
    >
    >> > Just ignore them, that's just typical "background noise" whenever people
    >> > can tell, you are using MS products (from the name of your

    >
    >> > What has hit you is a classical case of so called "undefined
    >> > behaviour" in C++, something totally on topic for this newsgroup ;-)

    >>
    >> ...or maybe it's something MS-specific ;-)

    >
    > To be honest, there probably will be some kind of "MS-specificity" to
    > the problem. Linking is notoriously underdefined by language standards,
    > you've got no chance to keep this area free of platform specific
    > information. But that's a problem of C++, too.


    As it turns out, the OP's problem had nothing to do with linking or
    MS-specificity, but - as you correctly guessed - with the well-known
    "gotcha" of global object initialisation order.

    The point I was trying to make is that had the OP posted code we might have
    spotted this straight off - and nobody would have had valid cause to
    complain about MS-specificity since it would have been clear that this was
    not the issue... this despite the fact that the OP himself seemed to think
    it /was/ an MS-specific (or possibly linkage) thing and therefore
    shouldn't have posted here! You might say he accidentally posted to the
    correct forum through ignorance... :)

    --
    Lionel B
     
    Lionel B, Dec 13, 2006
    #9
  10. Allen

    F.J.K. Guest

    Lionel B schrieb:

    > not the issue... this despite the fact that the OP himself seemed to think
    > it /was/ an MS-specific (or possibly linkage) thing and therefore
    > shouldn't have posted here! You might say he accidentally posted to the
    > correct forum through ignorance... :)


    sometimes, ignorance is bliss ;-)
     
    F.J.K., Dec 14, 2006
    #10
    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. prem
    Replies:
    1
    Views:
    1,609
    Shankara Narayanan
    Nov 3, 2004
  2. davidb
    Replies:
    2
    Views:
    1,025
    davidb
    Aug 30, 2006
  3. Mr. SweatyFinger

    why why why why why

    Mr. SweatyFinger, Nov 28, 2006, in forum: ASP .Net
    Replies:
    4
    Views:
    905
    Mark Rae
    Dec 21, 2006
  4. Mr. SweatyFinger
    Replies:
    2
    Views:
    1,974
    Smokey Grindel
    Dec 2, 2006
  5. H. Simpson
    Replies:
    4
    Views:
    282
    H. Simpson
    Aug 3, 2004
Loading...

Share This Page