0

I have made this simple test program:

#include <iostream>

class test {
    public:
    void print() {
        std::cout<<"hello world!"<<std::endl;
    }
};

test* getPointer1() {
    return new test;
}

test* getPointer2() {
    test a;
    return &a;
}

int main() {
   test* test1;
   test* test2;
   test1=getPointer1();
   test2=getPointer2();
   test1->print();
   test2->print();
}

For what i know, when you return a pointer to a memory location, and the function ends, the pointer should point to a portion of memory that no longer exists. But i don't seem to be right: when you call test1->print() and test2->print(), istead of getting a segmentation fault, the program prints two time hello world!. Could you explain me why this occur? Thank you in advice and sorry for my bad english

WileTheCoyot
  • 513
  • 1
  • 5
  • 20
  • 2
    It is a common misunderstanding that C++ bugs will always crash your program, but that's not what "undefined behaviour" means. This has been answered hundreds of times on StackOverflow already, but see http://c-faq.com/ansi/experiment.html for a nice explanation – Jonathan Wakely Mar 21 '14 at 17:26
  • @JonathanWakely how could that help me? – WileTheCoyot Mar 21 '14 at 17:27
  • @WileTheCoyot, what do you mean "how could that help me?" You asked why your buggy program doesn't crash, the link I gave explains that broken programs don't always crash or burst into flames. What part do you not understand? – Jonathan Wakely Mar 21 '14 at 17:30
  • @JonathanWakely you posted the case i=i++; but i want to know why my program does not crash or give me segfault – WileTheCoyot Mar 21 '14 at 17:34
  • @WileTheCoyot, `i=i++` is one kind of undefined behaviour. Your program is another kind of undefined behaviour. Undefined behaviour means **anything can happen**. I assumed you would be able to understand that the problem of undefined behaviour applies to more than just `i=i++` – Jonathan Wakely Mar 21 '14 at 17:36
  • @WileTheCoyot tl;dr it's basically working by sheer luck combined with the fact that your program is very simple. There's no access checking on pointers in c++. – dutt Mar 21 '14 at 17:36
  • @JonathanWakely ok now i understand what happened, excuse me if i have made a duplicate post – WileTheCoyot Mar 21 '14 at 17:38
  • @JonathanWakely That's a beautiful quote: "Somebody told me that in basketball you can't hold the ball and run. I got a basketball and tried it and it worked just fine. He obviously didn't understand basketball." -Roger Miller – Elliott Frisch Mar 21 '14 at 18:52
  • @ElliottFrisch, yes, I think it's wonderful :) – Jonathan Wakely Mar 21 '14 at 19:34

4 Answers4

1
test* getPointer1() {
    return new test;
}

In the above, test is allocated on the heap and will not be destroyed until you explicitly tell it to do so. So the pointer will remain valid.

test* getPointer2() {
    test a;
    return &a;
}

In this function, however, you're putting an instance of test on the stack and returning a pointer to an address in the stack. It appears that the second call works because that stack address hasn't been overwritten yet by something else.

R M
  • 96
  • 1
  • 4
  • I suppose the second call succeeded because the `print` function does not interact with the object's memory. – lisyarus Mar 21 '14 at 18:39
  • Yes, it's using a string literal so it's in memory for the duration of the program. The problem would arise if the program were printing the value of a member variable. – R M Mar 21 '14 at 19:14
1

Try this main

int main() {
   test* test1;
   test* test2;
   test1=getPointer1();
   delete test1;
   test2=getPointer2();
   test1->print();
   delete test1;
   test2->print();
}

With this main you handle the memory leak from test1.

But when you do something good (handling the memory leak).

test2 comes crashing down blazing in flames.

Conclusion

Don't return pointers or reference to a local object that will get erased when going out of scope.

Claudiordgz
  • 3,023
  • 1
  • 21
  • 48
0

For what i know, when you return a pointer to a memory location, and the function ends, the pointer should point to a portion of memory that no longer exists.

No. It points to a portion of memory that no longer contains a valid object. Typically, the memory still exists, and is still accessible; on most platforms, making it inaccessible is either impossible or expensive.

Dereferencing the pointer gives undefined behaviour. In your case, calling the member function doesn't do anything that depends on the memory contents, so you see the function being called as if there were a valid object. You can't depend on that, though - the behaviour is undefined.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • so if in the mean time between the function return the pointer and i use it, another process use that location of memory, i get something different than hello world? – WileTheCoyot Mar 21 '14 at 17:32
  • @WileTheCoyot: Not in this case, since `"hello world!"` is a static string, and nothing will change that. If you printed the value of a member variable, then you might see something unexpected. – Mike Seymour Mar 21 '14 at 17:34
  • @WileTheCoyot, another process cannot use that memory, on most systems every process has completely separate memory spaces. But the memory is now invalid, so accessing it has undefined behaviour so **anything can happen**, _including_ printing the old invalid contents. – Jonathan Wakely Mar 21 '14 at 17:35
0

test1 should never crash since it creates the object on heap. It persists until you delete it (which you need to do BTW).

test2 could crash since it creates the object on the stack and it is deleted when leaving the function. It actually does not crash in your case because your software is so very simple. It probably does not overwrite the stack so the zombie object is still functional. In a real world application the object's memory location would be overwritten and it would crash or do something else unpredictable.

Silicomancer
  • 8,604
  • 10
  • 63
  • 130