Friday, December 10, 2010

A pet peeve

Quite often on various help sites I frequent I'll run into someone confused about pointers that wonders something like, "I've got two pointers that point at the same thing, do I delete both? One? Which?" etc... I've yet to see anyone but myself correct their use of the terms and I think that's because people aren't really paying attention to exactly what is going on and why the common phrase, "...delete a pointer...," confuses the issue. Experts do know what's going on, but still use the terms incorrectly. I think it's time that we stopped and I bet that by correcting use and correcting those using them wrong, we could improve the understanding of noobs.

The first and foremost thing that all noobs fail to get is that pointers are values. A 'pointer to T' is not anything magical but for the green developer they always seem to be. The reason being is that we don't hammer into them that 'pointer to T' is nothing but another value type. In fact, the only reason that 'T' is involved at all is so that the compiler knows how far to increment it when we do math on the value. Besides that, 'pointer to T' is ENTIRELY unrelated to T or any instance of T. The 'pointer to T' type is simply another value type that holds a number and allows a few additional operators to manipulate it: *, ->, and delete.

The second thing that noobs seem to misunderstand is that they think 'pointer to T' somehow holds a T; this couldn't be further from the truth. The T that is 'pointed to' by a 'pointer to T' is exactly like any other T that you might create. It looks the same, acts the same, it IS the same. There doesn't even have to be any difference in location because 'pointer to T' can still 'point at' a T that was simply created as a value on the 'stack'. Another way of showing it is to point out that you can use new (or malloc) to create a T on the free-store (or heap) and not have any pointer anywhere: 'new T;'. That T exists just like it would with a pointer and is exactly the same shape as any other T created anywhere else. All that the value type 'pointer to T' does is tell you how to find it.

The next thing that noobs misunderstand, and this is the one I think experts should work harder to correct even in themselves, is that you do not delete (or free) pointers; you delete what they point at. Since a 'pointer to T' is a value type just like T is, it behaves just like T does. You don't delete them unless you created them with new. The only difference between 'pointer to T' and T itself (assuming T is not also a pointer type) is that it can be an operand of the delete operator. Passing a pointer into the delete function, by using the delete operator, tells that function to destroy the object pointed to by that pointer; you are NOT deleting the pointer. If that object is not on the free-store, or has been deleted already, then passing that pointer, a value that still exists and has the same value it always had, into the delete function results in very bad things. If you want to delete a pointer then you need to have a pointer to it and use THAT pointer as the delete operand; you will not be deleting the 'pointer to pointer to T' and hopefully the 'pointer to T' that 'pointer to pointer to T' points at was created on the free-store and still exists. In short, you NEVER delete value types that are not created on the free-store with the new operator and 'pointer to T' is not different in this regard.

So, the next time some noob asks something like:

I created an object with new, assigned it to ptr1 and then copied ptr1 into ptr2. Do I need to delete both pointers? Just one? Which one should I delete? What happens to the other one?...etc...

Please, when someone asks this, correct their terminology and your own. Explain to them that...

Neither. You don't delete the pointers, you want to delete what they point at. In order to delete an object you need to pass a value into the delete operator that contains a number representing the location of that object, a pointer. Since both of your pointers have the very same value, you can use either to delete the object they point to. Nothing happens to the pointers after that, and this is very important because they still contain a number representing a location that is no longer being occupied. You need to explicitly set those values to 0 so that you can tell again later or you need to destroy those pointers by allowing them to go out of scope.

Of course some people think that you shouldn't set a pointer to 0 because doing so hides "dual delete errors". Those people are retards though and are trying to debug through undefined behavior, which is just plain stupid.

At any rate, the point is to make sure that people understand that a pointer is simply another type of value. You do not delete it unless you've newed it and nothing is done to it by passing it as an operand to delete.

No comments:

Post a Comment