-2

The first call to printf in the number() function prints the string that was in token[] at the end of its last call. Can anyone explain the reasoning behind this?

I deleted most of the function commands that are not related to the string. If I needed to provide more code let me know.

PS : If I replace the token array with a char * and dynamically store and free the address I have no such issue

void number(FILE *fp, FILE *fo, char ch)
{
       char token[100],*tmp; //characters read are saved here
       State currentState = S0;
       State prevState;
       int i,counter = 0;

       printf("THE PREVIOUS TOKEN = %s\n\n",token);


       while(1)
       {


            switch (currentState)
            {
                    case S0 :
                    {
                            ...
                    }
                    case S1 :
                    {
                            ...
                    }
                    case S2 :
                    {     
                            ...
                    }
                    case S3 :
                    {
                            ...
                    }
                    case S4 :
                    {
                            ...
                    }
                    case S5 :
                    {
                           ...
                    }
                    case INTEGER :
                    {
                           ...
                    }
                    case FLOAT :
                    {
                            ...
                    }
                    case BAD :
                    {
                            dbg("  BAD\n");
                            prevState=BAD;
                            fprintf(fo,"+Error! Invalid syntax for an integer or float\n");
                            tmp=avoidchars(fp,ch);
                            if(tmp)
                            {
                                printf("Unknown token : %s\n\n",strcat(token,tmp));
                                free(tmp);
                            }
                            break;
                    }

               }



                if ( ( currentState==GOOD ) || ( currentState==BAD ) && ( prevState == BAD ) )
                      break;

                if( currentState != INTEGER  &&  currentState != FLOAT && currentState != BAD)
                {
                        token[counter] = ch;
                        ch=fgetc(fp);
                }     

                counter++;
    }
}
Magisch
  • 7,312
  • 9
  • 36
  • 52
MattSt
  • 1,024
  • 2
  • 16
  • 35
  • 1
    You have *undefined behavior*, anything could happen. Try calling a couple of other functions in between the two calls to your `number` function and see what happens. – Some programmer dude Nov 20 '15 at 08:34
  • You are breaking the rules of the C language by reading out of `token` before assigning contents to it, and as such, anything can happen. – M.M Nov 20 '15 at 08:34
  • I tried calling a puts() in main before calling number() and no problem occured. Why the undefined behavior though? As for breaking the rules, even if i remove the printf line, the second printf which appends tmp to token appears to have the same issue. – MattSt Nov 20 '15 at 08:38
  • 1
    [Read this](http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope). – Lundin Nov 20 '15 at 08:39
  • @Lundin So is the only solution to initalize the array since i can not know if it still has its previous values or not? – MattSt Nov 20 '15 at 08:48
  • @matts Yes that is the only bug-free solution. – Lundin Nov 20 '15 at 08:52

2 Answers2

2

Uninitialized non-static local variables have an indeterminate value, doing just about anything with such a variable, except to initialize it, leads to undefined behavior. You should simply not do it.

But to explain the behavior here, think about that the compiler doesn't initialize these variables for you, they are after all uninitialized. However, if you call a function multiple times after each other this non-initialization policy simply means that the memory will stay the same between calls. If you call functions that have their own local variables which they modify between the calls to your function, then the second call to your function will have your local variables contain the value from the previous call to the other function.

Try for example

number(...);
printf("%s %s %s %s %s\n", "foo", "bar", "flux", "blam", "foblax");
number(...)

Now if you print out the token array in the second call (technically undefined behavior), the contents will be quite different from the contents left by the previous number call.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
2

Printing an uninitialized variable is undefined behavior, so you are essentially asking "how undefined is undefined behavior".

There are no guarantees of what will happen when you print uninitialised data: you might get garbage, you might get something that seems to make sense, you could get a program crash. You might get something printed that makes sense today and have the program crash tomorrow. The program might work fine on your machine but crash at your customer's machine. There are no guarantees and no predictable behavior.

Behind the scenes of your specific system, it is likely that the array is stored on the stack. If you are lucky, that area of the stack is not modified between function calls, why it might seem as the memory is preserved. It is a bad idea to design a program which relies on luck though. If you actually need to preserve the array, it needs to be declared static, which will also force an initialization to a predictable value.

Lundin
  • 195,001
  • 40
  • 254
  • 396