0

I came across an example in a page outlining the various ways to represent a string in C structures. It explains that an array defined in a function outside main will be stored in the stack segment and as such will not necessarily be present following its return potentially causing a runtime error.

HIGHLIGHTED POSSIBLE DUPLICATE EXPLAINED WHY THE ARRAY FAILED ON RETURN I.E THE POINTER TO ELEMENT 0 RETURNED IS NO LONGER VALID BUT DID NOT SHOW THAT THE REASON VARIABLES OF THE SAME STORAGE CLASS (AUTO) ARE SUCCESSFUL IS THAT THEY PASS A VALUE WHICH SURVIVES THE REMOVAL OF THE STACK FRAME

" the below program may print some garbage data as string is stored in stack frame of function getString() and data may not be there after getString() returns. "

char *getString() 
{ 
  char str[] = "GfG"; /* Stored in stack segment */

  /* Problem: string may not be present after getSting() returns */
  return str;  
}      
int main() 
{ 
  printf("%s", getString());   
  getchar(); 
  return 0; 
} 

I understand that other local C variables will also be defined in their respective stack frames and obviously they can be returned so why is it an issue for arrays?

Thanks

nrmad
  • 422
  • 9
  • 19
  • Because in the other cases, the value itself is returned. If they too, returned a *pointer* to the local variable, the same would be true. – Weather Vane Feb 20 '19 at 00:14
  • Possible duplicate of [error: function returns address of local variable](https://stackoverflow.com/questions/12380758/error-function-returns-address-of-local-variable) – Govind Parmar Feb 20 '19 at 00:57

3 Answers3

5

This should roughly explains what happened, after return from getString(), its stack is not valid anymore.

         ^            ^ 
         |  not valid |    ^            ^
         +------------+    | not valid  |
  str--> | "GfG"      |    | not valid  | <---+
         |  ---       |    | not valid  |     |
         | stack of   |    +------------+     |
         | getString  |    | return(str)| ----+
         +------------+    | ---        |
         |            |    |            |
         | stack of   |    | stack of   |
         | main()     |    | main()     |
         +------------+    +------------+

If compiled with gcc -W -Wall (should always use those options), it should give the warning:

warning: function returns address of local variable [-Wreturn-local-addr]
KL-Yang
  • 381
  • 4
  • 8
  • Is a string constant like `"x"` stored in the stack? It might be stored somewhere in the data segment. – tadman Feb 20 '19 at 01:00
  • 1
    with or without const, gcc(6.3) all give the same "warning: function returns address of local variable [-Wreturn-local-addr]", which imply it might be stored on stack too. – KL-Yang Feb 20 '19 at 01:59
  • Good on GCC, then! – tadman Feb 20 '19 at 02:22
4

The difference is in returning a value as opposed to returning a pointer.

When you do this:

int f()
{
    int x = 9;
    return x;
}

int main()
{
    int a = f();
    printf("a=%d\n", a);
    return;
}

This is valid because even though x is out of scope when f returns, it is the value stored in x (9 in this case) that is returned. That value is then assigned to a and subsequently printed.

In your example you're returning an array. In most contexts, an array used in an expression decays into a pointer to its first element. So return str is the same as return &str[0]. That pointer value is returned and passed to printf. Then printf tried to dereference that pointer, but the memory it points to (the array str) is no longer valid.

So you can return values from a function, but if that value is a pointer to a local variable it will not be valid.

dbush
  • 205,898
  • 23
  • 218
  • 273
0

There are 2 situations:

  1. When you return a simple value like an int or char from a local function and that variable is defined/declared in that local function. It happens successfully, because while returning the value is actually copied.

  2. Now you have string "GfG" in str and when you do return str, the value that is copied is what is there in str and that is the address location of the array. So in this case the array location (pointer) is copied, while the contents of this array vanishes (since the contents were on local stack frame).

Syed Waris
  • 1,056
  • 1
  • 11
  • 16