Skip to main content
GameDev.net gamedev.net
🔒 Locked

Why this works?

Started by Jnz86 Dec 13, 2005 at 7:16 AM 16 replies 2.4k views
Original Post
Jnz86
Jnz86
Why this works, when it shouldn't (atleast i think so):

char* do_something()
{
  char t[101];
  .. // do something with string t
  return &t
}
Now i am creating object t in scope of this function, also i am returning at the end of the function. Shouldn't object t be destroyed after the exit from the function (just after return)?
Nitage
Nitage
In a release mode, the memory used by t won't be overwritten until something else is put on the stack - so that will probably work in the short term.

In a debug build the compiler will probably insert code that overwrites t's memory to help you catch problems like this.
Enigma
Enigma
The behaviour is undefined. t is deallocated when the function exits, but since it is stack allocated this deallocation usually just involves a modification of the stack pointer. The memory t occupied isn't immediately overwritten, it's just marked as available again. Until the point that the stack memory that t existed in is reused many operating system/compiler combinations will not object to you accessing that memory as if t still exists. Usually. However, this is not something you should rely on. It is also perfectly acceptable for your compiler to zero-out the memory when the function returns, or request the operating system mark the memory area invalid, in which case access after the function has returned will just crash. To misquote the Nike slogan, "Just don't do it".

Enigma
Jnz86
Jnz86
I thought about the same, but wasn't sure!
Thanks!
r++ both of you! :)
RITZ
RITZ
In order for it to work however you will need to make t static, or dynamically allocated so it doesn't go out of scope with the stack frame. But the best solution is the pass a pointer to an array to be filled rather than returning a pointer.
demonkoryu
demonkoryu
Any compiler worth it's salt should emit a warning. One reason to always compile with full warnings.
bitterbanana
bitterbanana
When you return &t, you're actually supposed to return t. t is already a pointer. Think of t[1] as *(t+1).

But here's a way that will work.

char* do_something(){   char *t = (char *)malloc(101);   // do something   return t;}


char t[101] is basically the same as char *t = (char *)malloc(101), except malloc allocates it separately, which keeps it alive after the function ends. I use this to return strings. But I use free(t); when I'm done with the string to keep my memory clean.
bitterbanana
bitterbanana
It's not a local variable if you manually allocate a block of memory using malloc. It'll only free the block if you use free(variable). The only thing that's pushed on the stack is the pointer to that memory block. The pointer is pushed off the stack when the function is done, but the memory block is not deallocated.
intransigent-seal
intransigent-seal
Quote:
Original post by Anonymous Poster
Anyways, if I am correct, won't malloc(101) just allocated void* memory on the heap with a size of 101 bytes? Unless a char is a byte, I don't think that will work out. But then again, maybe I am wrong ;P?

A char is a byte, so you are wrong, and bitterbanana's code will work (although obviously the caller will have to remember to free() the block after it's done with it.)

John B
The best thing about the internet is the way people with no experience or qualifications can pretend to be completely superior to other people who have no experience or qualifications.
iMalc
iMalc
Quote:
Original post by Jnz86
Why this works, when it shouldn't (atleast i think so):
char* do_something(){  char t[101];  .. // do something with string t  return &t}

Now i am creating object t in scope of this function, also i am returning at the end of the function.
Shouldn't object t be destroyed after the exit from the function (just after return)?
Even after removing the '..' and the the incorrectly used '&', any decent copmiler should still at least give you a warning...
warning C4172: returning address of local variable or temporary
"C allows you to shoot yourself in the foot." You've found a simple example to illustrate that point.
Conner McCloud
Conner McCloud
Even with the warning, his question is still a good one. That code resulting in a warning rather than an error suggests the code works, when in reality it doesn't.

I'm at a loss at the moment to think of any situations where such code wouldn't be an error, but I'm sure they exist.

CM
bitterbanana
bitterbanana
We've established that this works:

char* do_something(){   char *t = (char *)malloc(101);   // do something   return t;}
Conner McCloud
Conner McCloud
Quote:
Original post by bitterbanana
We've established that this works:

*** Source Snippet Removed ***

If that was in reference to my statement about situations where the warning is unjustified, your example means nothing, as it shouldn't generate the warning in the first place. You are returning a copy of a local variable, not a reference to one.

*edit: Although, I suppose if the compiler can issue the warning by mistake for code like that, then you'd have a good reason to not make it an error outright.

CM
owiley
owiley
Thats more of a logic error not compiler error...Some compilers will let you know that this shoud be looked at but normally peoples ignore warnings so this is a bug that will cause some headaches.

p.s.I really have no clue of why some would want to do that.Why go to hell when you dont have too?
Bring more Pain
MaulingMonkey
MaulingMonkey
Quote:
Original post by Jnz86
Why this works, when it shouldn't


Pure, blind luck.

POD types like char arn't "cleaned up" - there's nothing to clean up. There's no reason to zero it because that'd just waste processor time (since you should never try to access it after it's been destroyed anyways).

If the returned value happens to still contain the old values and not segfault, that's just luck. If the next function you call has any variables, even if totally unrelated, it will most likely change the data pointed to by the pointer originally returned.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.