3

I came across this page that illustrates common ways in which dangling pointes are created.

The code below is used to illustrate dangling pointers by returning address of a local variable:

// The pointer pointing to local variable becomes  
// dangling when local variable is static.
#include<stdio.h>

int *fun()
{
    // x is local variable and goes out of scope 
    // after an execution of fun() is over.
    int x = 5;

    return &x;
}

// Driver Code
int main()
{
    int *p = fun();
    fflush(stdout);

    // p points to something which is not valid anymore
    printf("%d", *p);
    return 0;
}

On running this, this is the compiler warning I get (as expected):

 In function 'fun':
12:2: warning: function returns address of local variable [-Wreturn-local-addr]
  return &x;
  ^

And this is the output I get (good so far):

32743

However, when I comment out the fflush(stdout) line, this is the output I get (with the same compiler warning):

5

What is the reason for this behaviour? How exactly is the presence/absence of the fflush command causing this behaviour change?

Arpith
  • 570
  • 2
  • 10
  • 26
  • 1
    http://stackoverflow.com/a/6445794/12711 – Michael Burr Apr 23 '17 at 02:41
  • "*What is the reason for this behavior?*" It's **Undefined Behavior**. Your use of `fflush` is irrelevant. (`fflush` empties the contents of `stdout`, but since you have nothing buffered, it serves no legitimate purpose). You may get `5` you may get a `Segmentation Fault`, it's **Undefined**. – David C. Rankin Apr 23 '17 at 04:53

2 Answers2

3

Returning a pointer to an object on the stack is bad, as you've mentioned. The reason you only see a problem with your fflush() call in place is that the stack is unmodified if it's not there. That is, the 5 is still in place, so the pointer dereference still gives that 5 to you. If you call a function (almost any function, probably) in between fun and printf, it will almost certainly overwrite that stack location, making the later dereference return whatever junk that function happened to leave there.

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
  • Wouldn't printf() also be put on the stack? Which would cause the address pointed by the pointer to be overwritten by something else (possibly)? – Arpith Apr 23 '17 at 02:23
  • Anything is possible. Clearly that doesn't happen in your case, though. – Carl Norum Apr 23 '17 at 02:25
  • I see. Tried with a simple sleep(1) and that did the trick. Thanks for the help @CarlNorum – Arpith Apr 23 '17 at 02:32
0

This is because calling fflush(stdout) writes onto the stack where x was.

Let me explain. The stack in assembly language (which is what all programming languages eventually run as in one way or another) is commonly used to store local variables, return addresses, and function parameters. When a function is called, it pushes these things onto the stack:

  • the address of where to continue executing code once the function completes.
  • the parameters to the function, in an order determined by the calling convention used.
  • the local variables that the function uses.

These things are then popped off of the stack, one by one, simply by changing where the CPU thinks the top of the stack is. This means the data still exists, but it's not guaranteed to continue to exist.

Calling another function after fun() overwrites the previous values above the top of the stack, in this case with the value of stdout, and so the pointer's referenced value changes.

Without calling another function, the data stays there and is still valid when the pointer is dereferenced.

  • 2
    I coded on a system once where a stack was not used for local variables and function arguments – M.M Apr 23 '17 at 02:43
  • If OP is programming on a x86 or x86-64 system (most personal computers), then a stack is used for local variables and function parameters. If they are programming on an embedded system, then OP should ideally know about the idiosyncrasies of their chosen system, and act accordingly. Returning a pointer to a local variable is undefined behaviour anyway. –  Apr 23 '17 at 06:44