2

Suppose the following simple code:

int main(void){
  char *p;
  int i = 1;
  while(i){
    char str[] = "string";
    p = str;
    i = 0;
  }
  /* Can I use above string by using `p` in here? */
  return 0;
}

I declared a string (char array) as local variable only valid in while{}. But I saved its array address to the pointer p which is also valid outside while{}. Is it okay use the string outside while{} by using p?

If it is okay, why does it work?

Analysis
  • 240
  • 1
  • 11

4 Answers4

2

Is it okay use the string outside while{} by using p?

No. In the scope of while p is pointing to first character of str. Outside of while there is no str and hence there is no valid memory location where p is pointing to.

You can achieve the desired effect by using static storage class specifier in str declaration

static char str[] = "string";  

Outside the while you can use p

printf("%s\n", p);  

This is because static variables declared within a block resides at the same storage location throughout program execution.

haccks
  • 104,019
  • 25
  • 176
  • 264
  • A cleaner solution would be to move the line char str[] = "string"; to above the while loop so it in scope for the duration of the loop and after. static would cause the variable to consume RAM permanently rather than be on the stack. – Ashley Duncan Apr 30 '20 at 21:14
  • @AshleyDuncan aA more cleaner solution would be allocate the memory dynamically for the string. – haccks Apr 30 '20 at 21:29
0

No, this is not OK. This is what is known as a dangling pointer. If you manage to use the memory before the program attempts to reuse this address, you may still get your expected result. However, if the memory is used again, you will get unexpected results and bugs that are very hard to locate.

mattm
  • 5,851
  • 11
  • 47
  • 77
  • Yes, but it's actually a bit worse than that. The code probably works reliably, as expected, in some C implementations, but C does not .require it to do so. Developing code relying on this behavior on an implementation that supports it sets a trap for anyone who tries to port it (possibly even to a different C implementation on the same platform). – John Bollinger Apr 12 '15 at 19:05
  • @John Bollinger: very true, it is a bear-trap waiting to bite! just changing compiler flags, optimization setting may trigger it, not to mention a newer version of the compiler... Undefined behavior absolutely must be avoided. – chqrlie Apr 12 '15 at 19:09
0

Try this as an example, it may not work with all compilers but in Xcode on OS X I get this result:

pa: apples
pa: orange
po: orange

#include <stdio.h>
char *pa;
char *po;

void apples(void)
{
    char sa[]="apples";
    pa = sa;
    printf("pa: %s\n", pa);
}

void orange(void)
{
    char so[]="orange";
    po = so;
    printf("pa: %s\n", pa);
    printf("po: %s\n", po);
}

int main(void)
{
    apples();
    orange();
    return 0;
}

Each function call to apples() and orange() subsequently grows and then shrinks the stack and you can see how the string (either apples or orange) ends up in the same memory location on the stack. But there are zero guarantees that string will be there once it is out of scope. This trick "works" here, but it is very dangerous.

As an additional exercise, try printing the contents of po in main() after the call to orange(), in most cases the string will be gone as the call to printf() overwrites that space on the stack.

Alan M
  • 194
  • 1
  • 8
-2

str points to the read-only (data) area of the process. You can access (read) that data with p, as well. However, attempting to write to that location will result in segmentation fault.

user2551017
  • 153
  • 10
  • But, inside the `while` scope, `"string"` is defined in `char []`, not in `char *`. I learned that character pointer saves string literal in read-only memory as you noted but in the case of character array, string literal can be modified. See I declared "string" in `char str[]`, which is of the second case, character array. It makes me confusing. (refer: http://stackoverflow.com/questions/1704407/what-is-the-difference-between-char-s-and-char-s-in-c, Rickard's answer. – Analysis Apr 12 '15 at 18:51
  • No. `str` is a local variable, allocated on the stack. The `"string"` is an *initializer*, not a string literal; it has nothing to do with where the elements of `str` live. – John Bollinger Apr 12 '15 at 19:00
  • You are correct. 7 bytes (6 for each character of "string" and 1 for terminating '\0') of memory were allocated on the stack and "string" got copied there. Since that memory is on the stack, using p you can both read and write there (just be careful not to write too much in order to not to result in stack overflow - unless that's what you want :) ) – user2551017 Apr 12 '15 at 19:02