1

I wrote the following code

#include "stdio.h"

struct node {
    int x;
    int y;
};
typedef struct node Node;

Node * f() {
    Node node = {1, 2};
    return &node;
}

int main() {
    Node *node = f();
    printf("(%d, %d)", node->x, node->y);
    printf("(%d, %d)", node->x, node->y);
}

During compilation, I get warning: address of stack memory associated with local variable 'node' returned warning.

However, the printf

  • prints the correct result the first time
  • prints the wrong result the second time

This brings me to my question: when exactly is the stack of the call to f() cleared??

blue_note
  • 27,712
  • 9
  • 72
  • 90
  • 5
    Its undefined behaviour, you are returning an address to an object which no longer exists after the call to f() ends. – Samer Tufail May 15 '19 at 10:27
  • `return &node;`: Dangling pointer innit. – Bathsheba May 15 '19 at 10:27
  • 4
    All local variables vanish as soon as the function they are declare in returns. That's what the compiler is telling you. It's actually more than a warning, because this is always wrong. – Jabberwocky May 15 '19 at 10:27
  • 2
    I believe that, in gcc, it will not be cleared, just overwritten in the next function call. Since you are accessing `node->x` and `node->y` in main, with no other function called after `f`, nothing had a chance to overwrite the values. The first printf probably does the overwrite so that the second one gets rubbish or an error. – nm_tp May 15 '19 at 10:29
  • @Jabberwocky: that's my point. It does not. It printst the correct result for 1-2 times, and after that it vanishes. – blue_note May 15 '19 at 10:29
  • 1
    *It printst the correct result for 1-2 times* Undefined behavior is undefined. – Andrew Henle May 15 '19 at 10:30
  • 1
    The behaviour is undefined - so it can print whatever it likes, or not. – Ted Lyngmo May 15 '19 at 10:30
  • 1
    why does it matter when it disappears? its UB. – Samer Tufail May 15 '19 at 10:30
  • 1
    Its never cleared. Accessing that stack variable is undefined behavoir and so technically anything can happen, including somewhat contradictory things such as printing the value twice gives different answerts. On a more technical level, although you shouldn't rely on this but its sometimes interesting to understand whats actually happening, is that the space that the variable in is still unused and so you can access it to call printf on it. However, the call to `printf` itself uses stack and writes over the value you left behind and were erronesouly accessing. – Mike Vine May 15 '19 at 10:30
  • 1
    It's undefined behaviour, so it can do whatever it pleases. It could even erase your hard drive. Check https://stackoverflow.com/questions/18506029/can-undefined-behavior-erase-the-hard-drive – mcabreb May 15 '19 at 10:36
  • 1
    In this case the "correct" result is just a mirage – Lightness Races in Orbit May 15 '19 at 10:36
  • 1
    @blue_note -- Unlike other languages you may have used, C++ has a concept called *undefined behavior*. Think of it this way -- if you had your drivers license revoked, does that mean you can't get into a car and drive it? Just because something is illegal doesn't mean you are stopped from doing it. The thing you need to be aware of is that anything can happen doing the illegal action. You may be stopped by a policeman after driving the car 100 feet, or you could drive for years and not be stopped. Your program could crash right away, or run for years and not show any issues. – PaulMcKenzie May 15 '19 at 11:05
  • A number of comments here comment on “undefined behavior” and imply or suggest the causes cannot be known or that inquiry is pointless. These comments are misguided at best. First, “undefined behavior” in the C standard merely means the standard imposes no requirements. There are other causes than the C standard, and it is worth inquiring about these, because it is useful to know how compilers work, how various features of C can be or are typically implemented, and how hardware works.… – Eric Postpischil May 15 '19 at 22:51
  • … For example, the pattern of an object apparently having a desired value immediately after a function return but not after a successive call is a big clue that there is a bug of returning the address of a local object. So knowledge of this pattern, and its cause in how the stack is used, can aid debugging. Additionally, understanding how the compiler uses the stack to implement function calls and local objects can aid in designing good programs or, ultimately, implementing compilers.… – Eric Postpischil May 15 '19 at 22:53
  • … We should understand that many people who ask these questions are not trying to learn what the C standard says about the situation but about how software and hardware is acting. The author of this question gives indications of this: they acknowledge the compiler warning and acknowledge the use and alteration of the stack. This curiosity should be satisfied: Imparting knowledge, not just of the **abstract** C model but of **actual** implementation is a good thing. The knowledge is valuable and useful and should not be fobbed off as “undefined behavior.” – Eric Postpischil May 15 '19 at 22:56

0 Answers0