0
#include <stdio.h>
#include <malloc.h>

void test( int * );

struct node
{
    int data;
    struct node * next;
};

int main()
{
    int * count;
    int b = 1;
    count = &b;
    test( count );
    test( count );
}

void test( int * count )
{
    struct node * temp;
    if ( *count == 1 )
    {
        temp = (struct node*)malloc( sizeof( struct node ) );
        *count = 2;
        temp->data = 2016;
        printf( "\n%d      %u\n", temp->data, temp->next );
    }
    else
    {
        printf( "\n%d      %u            2count\n", temp->data, temp->next );
    }
}

Since I know that when a function get called then a stack is created by the compiler in the memory and when the function ends (ends in the sense i.e when the control returns to the line next to the calling function inside the main function, in my case) then the stack of that function gets deleted and therefore all the variables local to that function should also get delete , but according to the above written code , the temp variable called by second test call restores the content of the first call , Why it is so ?

Even if you insert printf( "\n%d %u\n", temp->data, temp->next ); after second count call i.e at the end of main function , you will definately face 'not declared in scope' error which means it's neither global

Gaurav Joshi
  • 67
  • 1
  • 10

3 Answers3

0

Q. During the second call to function test(),
why does the temp variable retain its content set during the first call to test()

The stack is NOT zero-ed after use.

Please read the legendary "Hotel Keys" answer for a good understanding.

Update : Please note that the detailed explanation below assumes a commonly used memory management system. It contains references to stack and heap. However, the crux of the matter is that access to unintialised local variables will result in undefined/unspecified behaviour. Which means one could read uninitialised local variables as all 0s or all 1s or 42 or anything else.


For a moment, ignoring the issues with readability and type safety in the sample program, look at these 2 lines of code in your main() function:

test(count);  <-- Here you set the value of a local variable temp

which does

struct node * temp;
temp = (struct node*)malloc( sizeof( struct node ) );
temp->data = 2016;
printf( "\n%d      %u\n", temp->data, temp->next );

...and is immediately followed by...

test(count);  <-- Here you try to access the value of a local variable temp

which does

struct node * temp;
printf( "\n%d      %u            2count\n", temp->data, temp->next );

To continue with the hotel-keys analogy here,

You go to a hotel and book a room. your first time in a room you go ahead and set the air-conditioner to pleasant 20 degrees Celsius.

Later you check-out of the hotel. But immediately go back and book a room in the hotel again. The hotel gives you the same room (the key you had just returned was on the top of the stack of the keys at the concierge).

Now when you go back to the room a second time,

Would you be surprised if you checked the temperature of the air-conditioner (without setting it first) and found it to be 20 degrees Celsius?

The fact is the hotel, concierge (operating-system, C-library) made no guarantees that the air-conditioner settings (values on the stack) will be reset to some default value before giving you a room.


1. Of-course there will be hotels that provide such a service of reset-ing everything in the room to a default state before letting it out, and so will exist OSes/frameworks that scrub the stack between re-use.

2. A security-conscious person before checking out of his hotel room checks for any personal notes of his and ensures that a piece of paper with his bank-account number and mother's maiden name written on it isn't accidentally left back. Similarly if you are concerned about accidentally leaking any secret information by leaving it in a local variable on the stack then better set all local variables to 0 (or random values) before returning from the function.

3. The fact that the variable temp seems to retain its value between 2 invocations of a function test() is simply because the memory location used to hold temp was the same during the 2 time test() was invoked. Between the 2 invocations of test(), the memory location was marked as free memory, but nobody else wrote to the memory location in between the 2 invocations of test().

4. In your example code, note that the actual data and next may be store on the heap (or wherever malloc() allocates from). But the local pointer temp continues to be on the stack.

Community
  • 1
  • 1
TheCodeArtist
  • 21,479
  • 4
  • 69
  • 130
  • In that problem the function itself is returning the pointer but in my case there is no as such getting back of addresss , Is it wrong to say that stack get zero-ed after use ? – Gaurav Joshi Jan 30 '16 at 09:29
  • @GauravJoshi if you allocate a local variable (in this case `temp`), do not initialise it and immediately access its contents (`temp->data` and `temp->next`) it can have anything. In this case the same function was recently called during which `temp` was initialised. Thus the memory location on the stack being used to store `temp` when the `test()` function is running for the second time, contains the last value `temp` had when the `test()` function was executed for the first time. – TheCodeArtist Jan 30 '16 at 09:46
  • But as soon as the function complete its execution then it has been completely removed from the stack , now it has no existance , so I think its not good to say that it reallocate the previous value @TheCodeArtist – Gaurav Joshi Jan 30 '16 at 10:04
  • Just because the function exited doesn't mean parts of your system memory will be burnt to ashes. Nor does it mean that all the bits in the memory locations that were being used by the function will be immediately set to `0`. Subsequently, any function that accesses the contents of the stack (eg. using uninitialised local variables) can and will see the last value of all the variables of the function that just exited. – TheCodeArtist Jan 30 '16 at 10:14
0

There are a bunch of things wrong with the code. Have you tried compiling it...

foo.c:24:41: warning: format specifies type 'unsigned int' but the argument has type 'struct node *' [-Wformat]
printf("\n%d      %u\n" ,temp->data,temp->next);
                  ~~                ^~~~~~~~~~
foo.c:27:48: warning: format specifies type 'unsigned int' but the argument has type 'struct node *' [-Wformat]
printf("\n%d      %u  2count\n",temp->data,temp->next);

Please compile your code, indent it properly and add the compile time flags you used to compile it. Heres a reasonable set to start with

gcc   -g -Og -Wall -ansi -pedantic-errors -std=c99 foo.c
clang -g -O0 -Wall -ansi -pedantic-errors -std=c99 foo.c

or

gcc   -g -O3 -Wall -ansi -pedantic-errors -std=c11 foo.c
clang -g -O3 -Wall -ansi -pedantic-errors -std=c11 foo.c

This will show you some warnings, removing these warnings from your code and understanding them is what you need to do. Use the compiler, it's your friend.

Harry
  • 11,298
  • 1
  • 29
  • 43
0

Problems with your code.

a) Where does this done from #include <malloc.h> use #include <stdlib.h> As per the manual page http://linux.die.net/man/3/malloc

b) See below:

 void test( int * count )
 {
     struct node * temp;
     if ( *count == 1 )
     {
         temp = (struct node*)malloc( sizeof( struct node ) );
         *count = 2;
         temp->data = 2016;
         printf( "\n%d      %u\n", temp->data, temp->next ); <-- Where have you initialised temp->next
    }
    else
    {
        printf( "\n%d      %u            2count\n", temp->data, temp->next ); <- Where have you initialised temp!
    }

}

c) In the printfs - Why not read the manual for the correct format specifiers. Actually why not read the manual for the functions that you use and get familiar with them (along with indentation)

Ed Heal
  • 59,252
  • 17
  • 87
  • 127
  • I know but with gcc compilers you have to use malloc.h because gcc compilers have them as an alternative for stdlib.h (as in turbo c) – Gaurav Joshi Jan 30 '16 at 08:51
  • I am not sure where you read this. Besides make the code a bit portable – Ed Heal Jan 30 '16 at 08:52
  • actually I am creating a linked list program in c , the program run good , but when I tried some R&D in that code , then I found some unusual thing hapenning and this is just an easy representation of that unusual activity@Ed Heal , the problem is that why this code is compiling – Gaurav Joshi Jan 30 '16 at 08:55
  • C (and C++) give you enough rope to hang yourself (along with the rest of the people in the town). It has to have a good reason not to compile - and unfortunately for you this has not occurred. – Ed Heal Jan 30 '16 at 08:57
  • Hmm... that's why it is unusual and has now deadlocked my programing – Gaurav Joshi Jan 30 '16 at 08:59