Home > Back-end >  Function parameters behaving strangely in C
Function parameters behaving strangely in C

Time:07-08

Below is the sample code written in C:

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>

int* second;
void myTest1(int a, bool check){
    if(check){
        second = &a;
    }
    printf("%d", *(second));
    printf(" ");
}
int main(int argc, char const *argv[])
{
    int a =1;
    int b = 2;
    int c=3;
    myTest1(a,true);
    myTest1(b,false);
    myTest1(c,false);
}

I expect the output be like

1 1 1

But the actual output is

1 2 3

I am a bit confused about it, void myTest1(int a, bool check) here I believed a should have function scope. But it seems that the memory location of a is reused in every function call.

I am building by using command gcc <filename>.c

Below are some system details:

  • OS: Ubuntu
  • GCC compiler version: gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0

CodePudding user response:

You are setting second to the address of a variable that goes out of scope at the end of the function invocation. Once the variable is out of scope, the memory it occupied is no longer yours, and it can be reused. That memory address happens to be reused in each subsequent invocation, with the new argument's value copied into it.

Don't store the address of a local variable and access that address after the variable has gone out of scope. This produces undefined behaviour. You cannot make any assumptions about what may be on the other end of that pointer.

Regarding the following:

here I believed a should have function scope

It does...

But it seems that the memory location of "a" is reused in every function call.

Well, reuse is a necessary and natural result of a having "function scope". Unless you are assuming some kind of garbage-collection behavior, where keeping a pointer to this memory prevents it from being reused, a's memory location should be reused once a is inaccessible, otherwise this is the very definition of a memory leak. If the memory for function arguments weren't reused, every function invocation would leak memory by design.

In C and C it's your job not to store the address of stack-allocated variables that have gone out of scope (or at least, not to try to use that address after the variable has gone out of scope). The act of storing an address in a pointer does not innately protect that memory from reuse. It's up to you to either allocate that memory on the heap and manage its lifetime yourself, or to allow the stack to manage your memory and not hold onto pointers that outlive the lifetime the variables they point to.

CodePudding user response:

You're causing undefined behavior. When a function returns, all its automatic variables are destroyed, and any pointers to them become invalid.

On the second and third calls to myTest1(), second points to a variable from the first call. Since this variable no longer exists, dereferencing the pointer results in undefined behavior.

You're getting the result you see because in practice each successive call to the function happens to use the same location for the stack frame. So the address of a in each call is the same, so the old pointer will point to the value that was passed in the new call.

  •  Tags:  
  • c
  • Related