1

This is the code I've written,

    char *foo();

    void main()
    {
      char *str=foo();
      strcpy(str,"Holy sweet moses! I blew my stack!!");
      printf("%s",str);
    }

    char * foo()
    {
      char str[256];
      return str;
    }

When I use char array in function foo(), the strcpy in main() function doesn't copy the string into str. But, when I use int array in function foo(), main() strcpy copies successfully.

i.e.

   int str[256]; //in function foo

output

   Holy sweet moses! I blew my stack!!

if

   char str[256]; //in foo()

output : nothing!

BenMorel
  • 34,448
  • 50
  • 182
  • 322
mlemboy
  • 387
  • 2
  • 3
  • 15
  • You will get the same output. Check again! – Sankalp Sep 19 '13 at 06:51
  • nope.. i'm sure.. I've been testing it from an hour! – mlemboy Sep 19 '13 at 06:52
  • 3
    No matter whether you use int or char array within the function, what you are doing is wrong. The array goes out of scope when `foo()` returns. So you are returning a pointer to unallocated memory. – Alderath Sep 19 '13 at 06:55
  • @Alderath Please read the question properly.. That's our question only.. – mlemboy Sep 19 '13 at 06:57
  • @mahesh And I was saying that you are returning a pointer to unallocated memory. It is not possible to, in a general way, answer what is happening. What you are doing is undefined behaviour. Different compilers might produce different results. – Alderath Sep 19 '13 at 07:19

4 Answers4

5

What you are doing is clearly UNDEF, but.. Let's try to understand WHY it works with ints and not with chars..

TL;DR: printf uses the stack, overwriting some of the space pointed by str, but since the int array is bigger in memory than the char array, it is "far ahead" in the stack and doesn't get overwritten.

An int is 4 bytes, so 256 ints will be 1024 bytes.

If the array is in the stack, this will point to RBP - 1024 for example.

With chars, a char is 1 byte, 256 chars will be 256 bytes.

If the array is in the stack, this will point to RBP - 256 for example.

What does this mean? the str pointer will point to 1024 or 256 bytes "ahead" of the current stack pointer when foo returns.

SO.. when you call strcpy(str, "yourstring"); that memory could get overwritten with the stack that strcpy and printf uses. The thing here is that it IS overwritten but not all the stack, just a little, but enough to cover 256 bytes, and thus, that function can overwrite the copied string, this doesn't happen with your int array, because the string will be copied 1024 bits ahead of the stack pointer and strcpy and printf don't use so much stack.

Let me show you how your stack will end up:

enter image description here

If you change the size of the char array it will probably work.

All of this is undefined behaviour and completely depends on your architecture, computer and compiler. I'm using Linux x86_64 at the moment.

Marco
  • 2,796
  • 19
  • 24
  • 1
    Thanks for taking the time to do this.. I feel like it really drives the lesson home, OP is probably confused by people talking about undefined behaviour when he is still somehow getting his code to "work".. this really settles the issue. – qwwqwwq Sep 19 '13 at 08:03
2

Are you aware of Scope and Lifetime Of Variables Concept ? If you are, then you do know that what you are trying to do invokes "Undefined Behavior". You are lucky your code is even printing out something or not at all printing rather than referencing the unallocated memory and crashing due to Heap corruption.

From SO Soln::

To what extent are stack/heap controlled by the OS or language runtime?

The OS allocates the stack for each system-level thread when the thread is created. Typically the OS is called by the language runtime to allocate the heap for the application.

What is their scope?

The stack is attached to a thread, so when the thread exits the stack is reclaimed. The heap is typically allocated at application startup by the runtime, and is reclaimed when the application (technically process) exits.

What determines the size of each of them?

The size of the stack is set when a thread is created. The size of the heap is set on application startup, but can grow as space is needed (the allocator requests more memory from the operating system).

Community
  • 1
  • 1
Abhineet
  • 5,320
  • 1
  • 25
  • 43
0

When you function foo() returns, it returns address of a string from the stack. When function exits, your pointer is useless, because your string is removed from the stack when foo() stops. So you have a pointer to some place in memory, but can't tell what's there

Read compiler warnings, i bet there was at least one telling you that your function returns pointer to a local variable.(mine does and I did it a few times).

zubergu
  • 3,646
  • 3
  • 25
  • 38
0

From your string about blowing the stack I conclude that you know that what you're doing is wrong. Therefore my answer will be: Undefined behavior is undefined. When writing to memory that's not yours to write to anything can happen including things that you might expect and things that you might not expect. Other undefined behaviors might be marginally interesting to explore, writing to memory that doesn't belong to you isn't. It's always wrong, it will always do something you don't expect and there's no situation where the correct solution is anything other than not doing it anymore.

When you change the array from char to int, you change the size of the array and since most likely the stack grows down on your architecture it changes the address of the memory you're not supposed to overwrite in the first place.

Art
  • 19,807
  • 1
  • 34
  • 60