Click to See Complete Forum and Search --> : Memory mgmt issue
abcd_68
February 23rd, 2006, 09:26 AM
Hi all,
I've got an apparently trivial issue. Consider the following snippet (compiled with gcc 4 on ubuntu breezer):
const char* f() {
string s("foo bar");
return s.c_str();
}
int main() {
const char* c = f();
cout << c << endl; //shouldn't it crash?
}
I expect the "cout << c" instruction to cause a run-time error, as string::c_str() does not allocate memory but returns a pointer to the string instance's internal data. This data should be destroyed along with s by the time f() terminates.
I tried running the program through valgrind and still I got no errors. Eventually I tried on windows (vc++ 7.1) and rational purify finally reported an error.
Any ideas as to why everything runs smoothly on linux? I know this can be due to freed blocks not being returned immediately etc. but is this not an incident waiting to happen?
Thanks in advance
DragForce
February 23rd, 2006, 10:03 AM
I could be wrong but it deems to me that returning of a local variable by CONSTANT pointer/reference extends its timelife until the current line of code is being executed.
So if compiler does the following substitution:
cout << f() << endl;
then you have a perfectly valid statement.
Bob Davis
February 23rd, 2006, 11:00 AM
I think that the thing you're talking about only applies to const references, not just pointers. At best, I think you're looking at undefined behavior. So, depending upon your platform/compiler, it could work, not work, cause your computer to explode, etc.
Paul McKenzie
February 23rd, 2006, 11:45 AM
Hi all,
I've got an apparently trivial issue. Consider the following snippet (compiled with gcc 4 on ubuntu breezer):
const char* f() {
string s("foo bar");
return s.c_str();
}
int main() {
const char* c = f();
cout << c << endl; //shouldn't it crash?
}
I expect the "cout << c" instruction to cause a run-time error, Crashes are not guaranteed to be produced, no matter how disastrous or horrid the code may be. That being said, the code you have produces undefined behavior.
Any ideas as to why everything runs smoothly on linux?No, it isn't the OS (Linux). It is how the compiler has implemented (or not implemented) the underlying code to do this illegal behavior with pointers. You can just as easily get another brand of compiler that runs under Linux, compile your app, and the crash happens immediately.
Regards,
Paul McKenzie
googler
February 23rd, 2006, 03:16 PM
Any ideas as to why everything runs smoothly on linux? I know this can be due to freed blocks not being returned immediately etc. but is this not an incident waiting to happen?
When your program exhibits undefined hehavior, that means that anything could happen. You may get a compiler error, but may not. You may get a link error, but may not. You may get a run-time error with little or no memory corruption, but may not. You may get a run-time error with a lot of memory corruption, but may not. And finally, last, but not least, the program may.... gasp! .... work as expected! :eek:
To understand what's going on, you need to know a little bit about the underlying implementation. f() returns a pointer to a block of memory that's been deallocated. When memory gets deallocated from the heap, it doesn't disappear. Most of the time, all that happens is that flags in a header preceding the memory block get set to indicate that the block is now free. The memory occupied by the block won't get stomped on until and if you allocate another piece of memory in the same place. So if you access the memory again soon, whatever you put there may still be there. In fact, only on rare occasions do the heap functions actually return memory to the operating system. This happens if either large contiguous chunks of the heap have been freed and the heap management routines have some kind of garbage collection, or more likely when your program exits. When the memory gets returned to the operating system, it really does disappear (at least on virtual-memory systems.) Well, the physical memory never actually disappears, but the OS unmaps it from your application's address space, so you don't see it anymore.
abcd_68
February 24th, 2006, 03:38 AM
Thanks everyone for the answers but I'm afraid I didn't make myself clear enough.
I know this program is wrong, that the freed memory is not literally freed etc. etc. (BTW I have to say that googler's disquisition should belong in an operating systems handbook as it's really clear and precise).
My question (probably a bit OT) should have been: Why didn't valgrind catch the error? (this is what I meant by "running smoothly", my mistake). I even set --freelist-vol to a huge value but still the error went unreported. This seems a pretty trivial case of memory error so I thought it would be detected immediately. Purify on the contrary did catch it.
Thanks again
Paul McKenzie
February 24th, 2006, 04:47 AM
Why didn't valgrind catch the error?Maybe it has a bug or doesn't handle this type of construct correctly. Memory checking software isn't infallible. Why not give this example to the valgrind developers and have them figure it out.Purify on the contrary did catch it.No different than "why can software A do xxxx, while software B can't do xxxx?"
Anyway, your example is simple enough -- there shouldn't have been a reliance on memory checking tools to give the thumbs up or down as to whether it is a bug or not. What memory checking tools should be used for are cases where the management of memory gets gnarly and obsfuscated, and it really isn't possible for a programmer to figure out the problem in a reasonable amount of time (due to code size or some other factors).
Regards,
Paul McKenzie
googler
February 24th, 2006, 05:23 AM
I know this program is wrong, that the freed memory is not literally freed etc. etc. (BTW I have to say that googler's disquisition should belong in an operating systems handbook as it's really clear and precise).
Sorry for being overly pedantic, but there's an unrelated thread on virtual functions where someone asked why he's not getting a compiler error for doing something that's undefined in the standard, so I kind of lost it. Worse yet, there's also a situation there as well where the expected function ends up being called sometimes, even though the code is invalid, so people don't believe it's possible this is undefined behavior.
As for valgrind - I guess you should demand your money back (or maybe it's "you get what you paid for" ?)
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.