Question

I am getting this error

error: Access.Core may be used uninitialized in this function

And this is my code:

 static int FirstTime = 1;
 MyStruct Access;

 if (FirstTime) {
   FirstTime = 0;
   Access = Implementation();
   DoSomething(Access);
 }

 if(Other_Variable) {
    Access = Implementation2();
    DoSomething(Access);
  }

  //The Other_Variable will be set to 1 and to 0 by other part of the code

My code is like that because I want to call to the function Implementation only the first time. In every call the Access variable is going to be updated so it does not make many sense make it static.

If I make Access static works, but I do not like make it static because in every other call Access is going to be updated. Any way to avoid the problem without making it static?.

Also any better options to execute only once a function instead of using a static variable are welcome.

Was it helpful?

Solution

Make Access like this (and remove FirstTime and the if):

static MyStruct Access = Implementation(this_b);

The reason you get this warning is because static variables survive one function call. Their value is retained across all function calls (without regard to which thread calls that function). So, FirstTime will control whether you initialize Access. The first time you call the function that code is in will correctly initialize the Access variable. But with every further function call, FirstTime is zero, and you will not initialize Access anymore, and thus will use an uninitialized variable down the code.

Edit: Now, with your updated information, you say that you have two Implementation functions. The first time you want to use one, and all the other times you want to use another function. How about this then:

 // static will be false/zero by default
 static bool AlreadyCalled;
 MyStruct Access;

 if (!AlreadyCalled) {
   Access = Implementation();
   AlreadyCalled = true;
 } else {
   Access = Implementation2();
 }

Depending on your actual use case, there may be better ways to handle this, though. For example, why not update the state of Access, like this:

// let the default constructor initialize it
// to a plausible state
static MyStruct Access;

// use RAII to update the state of Access when this
// function returns. 
MyUpdater updater(Access);

// now, do whatever the function does. 

Something like this for MyUpdater:

struct MyUpdater {
    MyStruct &s;
    MyUpdater(MyStruct &s):s(s) { }
    ~MyUpdater() {
        s.ChangeState();
    }
};

That pattern is called RAII: You associate some useful action with the constructor and destructor of a locally allocated object.

OTHER TIPS

@litb's answer is interesting. An equivalent program follows. The code compiles and works as stated in C++, but doesn't compile in C.

#include <stdio.h>

static int newval(void) { return 3; }

void inc(void)
{
    static int a = newval();

    a++;
    printf("%d\n", a);
}

int main(void)
{
    int i;
    for (i = 0; i < 10; i++)
        inc();
    return(0);
}

gcc says:

x.c: In function 'inc': x.c:7: error: initializer element is not constant

g++ is quite happy with it.

That is a difference between C and C++ that I was not aware of (but this wouldn't fit into 300 characters so I can't make it a comment, easily).


@Eduardo asked one of the questions in the comments: "Why does C not allow this and C++ allow it?". Since the answer is more than 300 characters...

As @litb said in the comments, in C you can only use constants for initializers of static variables. This is in part because the values are set before main() is called, and no user-defined functions are called before main() is called. C++, by contrast, allows global and static variables to be initialized by (user-defined) constructors before main() is called, so there's no reason not to allow other user-defined functions to be called too, so the initialization is reasonable. With C89, you are limited in the initializers you can use with automatic (local) variables; in C99, you can use pretty much any expression to initialize any local variable.

Access isn't static, therefore a new instance is created everytime the function is called. Only on the first time through do you actually assign any value to it; this value is lost as soon the function exits.

If you need Access to persist across calls to the function, make it static.

Access is not static and therefore it must be created in every call.

Consider simplifying the code to something like:

static MyStruct Access = Implementation(this_b);

This ensures that the function will only be called the first time the method is run and that Access will hold the value between calls.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top