2

I am working with a collaboration on a big project. Due to our code's infrastructure, basically all functions must "return by reference":

void doSomething(TYPE &result) {
  // do something to result
}

However, I am running into some Segmentation Errors when trying to use references to pointers. Especially when I try to clean up the memory, bad things happen. To try and understand the segfaults, I made a very simple test code. My first attempt compiled and ran without any errors:

int main() {
  int* a;

  delete a;  // Seems to cause no problem!
}

Since this worked, I decided to try something similar with a reference to a pointer:

int main() {
  int* a;

  delete a;  // Suddenly, this line is an "invalid delete".
  int*& b = a;
}

Why does this suddenly segfault? Also, if a "proper way" exists to clean up the memory reserved by a pointer via a reference, what is it?

Some research notes:

I tried to find some answers here on StackOverflow. It should be safe to delete a NULL pointer according to Is it safe to delete a NULL pointer?... My pointer is totally uninitialized, so I might be doing something silly. However, in my big collaboration code, I would have to dig pretty deep to initialize this kind of pointer to NULL.

I also tried to learn about references to pointers in general. Another StackOverflow post suggested http://markgodwin.blogspot.co.il/2009/08/c-reference-to-pointer.html. That was a good read, but didn't solve my problem.

Thanks in advance!

  • Deleting something that's not been allocated is undefined behavior = anything can happen. Maybe a segfault, maybe nothing. – Emil Laine Mar 05 '15 at 18:32
  • 1
    Welcome to the wild and crazy world of Undefined Behavior. – NathanOliver Mar 05 '15 at 18:32
  • Btw references to pointers work exactly the same way as pointers. Nothing special there. Just as all reference variables behave just as their non-reference counterparts. – Emil Laine Mar 05 '15 at 18:36
  • Okay, so according to these comments, and the solution below, the most important thing is to initialize the pointer (at the very least to NULL). Well, now I get to dig deep within the guts of our code! Sounds like fun. Thanks everybody! – Abram Krislock Mar 05 '15 at 19:49

3 Answers3

2

Calling delete on an uninitialized pointer yields undefined behavior. Therefore it might not cause you problems sometimes but can crash other times.

Any type of access performed on an uninitialized variable (apart from initializing it) leads to undefined behavior. e.g. reading it, comparing it, deleting it.

Dermot Blair
  • 1,600
  • 10
  • 10
1

You're mistaken if you think that an uninitialised pointer will be NULL. It is actually uninitialised, and accessing its value causes undefined behaviour.

A statement delete a accesses the value of a which causes undefined behaviour in itself.

Using operator delete on any non-NULL pointer that was not produced by the corresponding operator new gives undefined behaviour (whether that pointer has a valid value or not).

Undefined behaviour can give any result. Including inconsistency like your describe.

Rob
  • 1,966
  • 9
  • 13
0

Your example is not great because "a" will only be NULL in debug mode and will be undefined in release mode. It could contain any random value.

You may want to create your objects on stack, like this:

void foo() {
 TYPE myObj; // this calls the default c-tor, creating the obj on stack
 // the object will de destroyed when the executions goes out of scope.
 // if you pass the object reference to another function that keeps the 
 // reference for future use you are in trouble, as the object will be 
 // destroyed when out of this scope...

}

Alternatively, create the object on heap, using new :

void foo() {
     TYPE * myObj = new TYPE(); // here you need to take care of 
     // destroying the object yourself  (delete myObj)

    }

Best is to use smart pointers. Check Boost, highly recommend. http://www.boost.org/

Calin Grecu
  • 76
  • 1
  • 6