2

I just upgraded to a new version of a third party library (QtPropertyBrowser for Qt 5.0). The upgrade led to a new bug in my application which I managed to track to a static function in the library. The function contains a static variable that is initialized the first time the function is called. I copied down the memory location of that variable after initialization and found, as expected, that on multiple subsequent calls that the variable remained in the same memory location. Then on a subsequent function call I noticed that the memory location and data in the static variable had changed (causing the bug in my program).

The code looks something like this:

class ClassA
{
    //.... 
};

class ClassB
{
public:
    ClassA* ptrMember;
};

static ClassA *theFunction()
{
    static ClassB statVar = {0};
    if(!statVar.ptrMember)
        statVar.ptrMember = new ClassA();
    return statVar.ptrMember;
}

I found that during multiple calls to theFunction() the address stored in &statVar always remained the same, but then on a subsequent call the address in &statVar was different and statVar.ptrMember was empty.

I didn't think this was possible! Any ideas?

8
  • 2
    Which of the above parts are in headers vs. cpp files? Commented Jan 22, 2013 at 17:25
  • Originally everything was templated in headers and called using complex macros. In order to debug what was going on I reproduced the classes and function without templates or macros and put them all in the relevant .cpp file. The issue is the same in both cases. Commented Jan 22, 2013 at 17:28
  • 1
    To clarify are you saying that the address of the static variable itself (&statVar) changes? Or that the pointer to ClassA inside it changes? The second is easily explained since you overwrite it each time the function is called; the first would be more mysterious. Commented Jan 22, 2013 at 17:29
  • You create a new ClassA each time you call the function. Is that intended? Commented Jan 22, 2013 at 17:29
  • 1
    A static variable is its address. It cannot change. You are looking at a different static variable in a different static function, thanks to the wonders of DLL technology and static libraries mashed together. Commented Jan 22, 2013 at 17:40

1 Answer 1

6

It looks like you've defined the function in a header file, and have included in many .cpp files (each .cpp file defines one translation unit).

Since the function is declared static, each translation unit gets its own version along with the static variable. That is why, the address of the static variable is different when you call the function from different translation unit. As long as you call it from same translation unit, you will see the same address.

Note that the address will remain same for a particular translation unit. It is just that each translation unit will have its own version of the static variable, hence different address; you're not accessing the same variable anymore, they're different variable with same identifier.


The problem is that this is all defined in a third party library and I need to call it from both a dll and an exe without the static variable getting reinitialized. Is there any way that I can take care of the problem without altering the code in the library? I am currently using the library as a .lib. Would the problem go away if I compiled it as a .dll instead?

To avoid multiple version of the static function (hence static variable), you need to call it from same translation unit. To do that, you can use proxy to call the function. That is, instead of directly calling the function, call a proxy (which is defined in a single translation unit, no more version).

  • Declare the proxy in a header:

    //proxy.h
    ClassA *proxy_of_theFunction();
    
  • Define the proxy in an implementation file:

    //proxy.cpp
    ClassA* proxy_of_theFunction()
    {
        return theFunction(); //call the actual function
    }
    

Call proxy_of_theFunction. That should solve your problem.

Since proxy_of_theFunction is not static (and it is defined in proxy.cpp), it has only one version; no other version. Since there is only one proxy from which you call theFunction(), you're calling the same version of theFunction everytime, hence you will see same version of static variable for every call. :-)

Sign up to request clarification or add additional context in comments.

3 Comments

The problem is that this is all defined in a third party library and I need to call it from both a dll and an exe without the static variable getting reinitialized. Is there any way that I can take care of the problem without altering the code in the library? I am currently using the library as a .lib. Would the problem go away if I compiled it as a .dll instead?
@Joey: I think you can do something. Some workaround. Let me suggest one solution.
Great idea! In my case its a little more complicated, but I think I can move the class that was using the code from the exe to the dll, which is effectively what you're saying. I'm trying that now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.