0

I had a bug which is resolved recently but I want to understand why. I have a cmake project using c++11.

This works on mac osx but not on ubuntu. It returns null on ubuntu.

obj *getPointer(){
  obj test = obj(1,2,3);
  return &test;
}

This works on both:

obj *getPointer(){
  obj* ptr;
  obj test = obj(1,2,3);
  ptr = &test
  return &ptr;
}
Guillaume Racicot
  • 39,621
  • 9
  • 77
  • 141
Nick
  • 43
  • 5

1 Answers1

11

Both of your instances invoke undefined behaviour (UB), as you are returning the address of a local object obj test with automatic storage duration which is being destroyed at the exit from the function so you end up with a dangling pointer. It just "happens" to work, but anything can happen, so you should avoid UB at all costs!

To understand why it happens to work, that's because probably at the exit from the function the function's stack is not yet reclaimed by the OS, so the dangling pointer happens to point to the same data.

This answer to Can a local variable's memory be accessed outside its scope? offers one of the best explanations I've ever seen about dangling pointers.

Community
  • 1
  • 1
vsoftco
  • 55,410
  • 12
  • 139
  • 252
  • What is the right way to do it? Should I pass the test obj from caller function like main? or should I create object with new key and delete it when everything is done in another function? – Nick Dec 16 '16 at 21:29
  • 1
    @Nick You should create it with `new` and release it with `delete`. Or better, use [smart pointers](https://en.wikipedia.org/wiki/Smart_pointer). – vsoftco Dec 16 '16 at 21:30
  • 3
    @Nick I think you should return it by value and let the compiler elide the copy. – Guillaume Racicot Dec 16 '16 at 21:34
  • 2
    Don't use `new`, do't use smart pointers, just return the object. `obj GetPointer() { ... return test; }`. Simple enough, and let the compiler make it efficient. – MSalters Dec 16 '16 at 21:34
  • make sense but my function does not guarantee return object imagine this function calls several times and one of them is give the object so for the other cases I return nullptr – Nick Dec 16 '16 at 21:40
  • 1
    actually not returning pointer to a local variable causes UB only using dereferenced value :) – W.F. Dec 16 '16 at 21:48
  • @W.F. True, indeed. – vsoftco Dec 16 '16 at 21:50
  • @Nick Relevant: [What can happen when you return a pointer to a local object.](http://coliru.stacked-crooked.com/a/6fdb31cb4054b7ab) Note that even though the return value from the second call to `retIntPtr()` is discarded, the object from the first call still changed. Once the function returns, all of the memory that it used was freed, including the object that was allocated. – Justin Time - Reinstate Monica Dec 16 '16 at 22:04
  • @Nick If you need to return a pointer, you should probably be using `new` and `delete`, or a smart pointer, like vsoftco said. [You won't run into that problem.](http://coliru.stacked-crooked.com/a/049a189ffde2b128) – Justin Time - Reinstate Monica Dec 16 '16 at 22:27