views:

2830

answers:

5

Hello,

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.

Thanks a lot in advance.

+1  A: 

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.

Michael
in addition to that, if it's static, you can get rid of the if and just initialize it in the declaration since that will only happen once anyway.
Evan Teran
A: 

As I am getting clobbered on reputation points for this answer, I'm deleting it.

Jack BeNimble
+5  A: 

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.

Johannes Schaub - litb
Except the if statement is not required at all, since just assigning it directly means it will retain its value and it will only be assigned once. Thus FirstTime is no longer required.
X-Istence
right, he can omit FirstTime and the other things now
Johannes Schaub - litb
The reason why I did not want to put Access as static is because is a big struct. And I do not want to have that variable everytime stored in memory just because that "silly" thing. The code is not complete but I know that in every call different that the first time I am going to update Access again
Eduardo
Eduardo, static variables will not be held on the stack. so the size will not really matter. if however everytime you have another value for access, it does not make sense to me to make it static. consider putting it on the stack and put a pointer into it pointing to something on the heap (new[]).
Johannes Schaub - litb
however, without more code we cannot more precisely help you with that, i think.
Johannes Schaub - litb
@litb, that's the thing I am saying I do not like a lot make it static because in every call is going to change. Can you explain a little more the method of putting it in the stack and put a pointer.... I added some more code, I hope that is enough, the whole code is a little more messy
Eduardo
i've updated my answer. maybe it fits your needs better now
Johannes Schaub - litb
The first one can't work because I need to take into account the Other_Variable, but the second one using RAII is really cool. Thanks!
Eduardo
Sorry about the continuous updating of the code, the reason why I cannot use the first solution is because Access does need to be updated everytime, I need to take into account other_variable
Eduardo
alright, forgiven :) well the reason i did not consider the Other_Variable is because you seem to say it is always set to 1 by another part of code in every other call than the first. so the if(Other_Variable) { .. } will always be true and code executed starting from the second call
Johannes Schaub - litb
+1  A: 

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.

smink
Hi this answer was good for my first code, but sorry I updated the code, and the reason why I do not want to make it static it is because it is not necessary. The next time I will use it I will update it again. If you see now the code now everything is much more clear. Sorry and thanks
Eduardo
+2  A: 

@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.

Jonathan Leffler
yeah that's an interesting difference between C++ and C. C89 is even more restrictive: it does not allow non-constant-expressions in aggregate initializers like struct { int a; } a = { newval() }; C99 lifts that restriction to the good :)
Johannes Schaub - litb
Hi any explanation about why c++ allow this and c no? Or just because the developers wanted to implement c++ like this.
Eduardo