11

I was asked this in a recent interview, basically writing a function to combine the functionality of free and assigning null. I answered in the following manner:

void main()
{
      int *ptr;
      ptr = new int;
      ptr = newdelete(ptr);
}

(int*) newdelete (int *ptr)
{
      delete(ptr);
      return NULL;
}

So after execution, the ptr local to main will hold the null value as I am returning it from the newdelete function. If I had just assigned NULL in the newdelete function, the ptr local to newdelete would be nulled and not the ptr local to main.

I think my solution was correct, the interviewer accepted it too. However, he was expecting some other answer. He was insisting I do not return the NULL from the function and still achieve the desired result.

Is there any way to accomplish that? All I can think of is passing another argument which is the pointer to the pointer ptr local to main, but I don't see why it's better than what I did!

Palec
  • 12,743
  • 8
  • 69
  • 138
Harshad Kshirsagar
  • 491
  • 2
  • 7
  • 11
  • I guess you meant `new int` because `New` is not a defined `C++` operator. – ereOn Jul 02 '10 at 07:09
  • 1
    Pass a reference to the pointer. – Martin York Jul 02 '10 at 07:10
  • http://stackoverflow.com/questions/1265666/reason-why-not-to-have-a-delete-macro-for-c/1265681#1265681 – Goz Jul 02 '10 at 07:31
  • 8
    In C++ it's `int main()`. Always. No Exceptions. – sbi Jul 02 '10 at 07:32
  • And I'd be very wary of a shop where they need to null their pointers. Why do they have naked pointers? And why do they keep them around after they aren't needed any longer? – sbi Jul 02 '10 at 07:34
  • @sbi In C it's arguably a pretty good practice, but it has no place in C++. For C, the pointers might be kept around if they are part of a struct, e.g., and when tracing through code we can easily tell what pointers own memory and what don't. – stinky472 Jul 02 '10 at 08:13
  • 1
    @Goz: and more precisely: http://stackoverflow.com/questions/1265666/reason-why-not-to-have-a-delete-macro-for-c/1265866#1265866 – Matthieu M. Jul 02 '10 at 09:32
  • @stinky472: Yes, but this has a `C++` tag. – sbi Jul 06 '10 at 07:03

4 Answers4

36

Is there any way to accomplish that??

template <typename T> void safeDelete(T*& p){
    delete p;
    p = 0;
}

int main(int argc, char** arv){
    int * i = new int;
    safeDelete(i);
    return 0;
}
SigTerm
  • 26,089
  • 6
  • 66
  • 115
  • 4
    Since there is only code, the reason why this is a better solution is that you guarantee that the pointer will be nulled during the call. With the code in the question you could just skip (forget) the return value: `/*p = */newdelete( p );` and the memory would be freed but the pointer would be non-null. – David Rodríguez - dribeas Jul 02 '10 at 07:22
  • 6
    Keep in mind that you would need a second version of this for arrays. – Björn Pollex Jul 02 '10 at 07:55
  • 2
    The question of course is: what's safe about this ? You hide bugs instead of checking them... – Matthieu M. Jul 02 '10 at 09:34
  • @Matthieu M: First, you need to prove that this is only useful for hiding bugs. – SigTerm Jul 02 '10 at 09:57
  • @Matthieu I wouldn't say it's safe, but in C it can be handy to null pointers after freeing them. For a start, it shows us in the debugger when a pointer is currently pointing to something valid and when it's not. Secondly, about hiding bugs, dereferencing a null is equally undefined as dereferencing pointer to freed memory. It also makes it easier to catch bugs with `assert(ptr);` On the flip side, it can hide bugs by encouraging shotgun debugging methods where people do a lot of null pointer checks regardless of whether a function requires a valid pointer to be passed in. – stinky472 Jul 02 '10 at 10:18
  • [...] plus it wastes clock cycles. However, I once worked in a poorly coded C system but I was at least thankful that the developers assigned pointers to NULL quite uniformly as their memory management schemes were terrible: allocating memory in one place only to deallocate it somewhere completely different. It was a nightmare but that coding practice was the only thing that kept me from completely losing my sanity. – stinky472 Jul 02 '10 at 10:21
  • 1
    @SigTerm: It's equivalent to a `try { } catch(...) { }` in that you potentially ignore an error (because you do check for NULL, don't you ?). Furthermore it doesn't address the problem of aliases: nulling one pointer doesn't null all the other copies of this pointer. In short: at worst it hides bugs, at best it's useless. I personally prefer a REAL ownership scheme using RAII. I linked an answer to a duplicate in the comments to the question. – Matthieu M. Jul 02 '10 at 12:17
  • @Matthieu M: I disagree. I don't think that the only use of this function is when there is an error. Besides, OP asked very precise "how to do it" question (which was asked on interview), so all discussion about possible bugs and other methods are mostly useless. Also, there is no warranty that pointer was ever copied, so "REAL ownership scheme" is not required. End of discussion. – SigTerm Jul 02 '10 at 15:30
  • 1
    @SigTerm: I agree to put an end to the discussion, we manifestly have very different opinions :) – Matthieu M. Jul 02 '10 at 16:44
  • @Matthieu M: Good, I like people that can accept existence of different opinion without arguing to the death. Have a nice day, your opinion was appreciated. With all due respect, SigTerm. – SigTerm Jul 02 '10 at 17:17
8

I guess he was expecting something like:

void reset(int*& ptr)
{
      delete(ptr);
      ptr = NULL;
}

An even cleaner solution would have been to use a boost::shared_ptr<> and to simply call ptr.reset(). However, I suppose this wasn't an option.

ereOn
  • 53,676
  • 39
  • 161
  • 238
  • 1
    What if they don't want shared pointer semantics? No point having that extra overhead if you don't need it. – Peter Alexander Jul 02 '10 at 07:30
  • 1
    @Peter scoped_ptr in that case which likewise provides reset. – stinky472 Jul 02 '10 at 07:36
  • @Peter: I should have mentionned `scoped_ptr` instead of `shared_ptr` (i use the latter more often so it came to my mind first). Whether it is shared or scoped, using a smart pointer is safer than any `safeDelete()` function combined with raw pointers. – ereOn Jul 02 '10 at 08:10
  • 1
    Upvoted this one, even though I'd use the template example, because it matches what they would want to see in the interview. The template example might waste more precious interview time, even if it is very simple. – Merlyn Morgan-Graham Jul 02 '10 at 10:27
1

If the requrement wasn't to write a function, you could always write a macro that would do it for you as well:

#define my_delete(x) { delete x; x = NULL; }

Of course, calling it like this will get you into all sorts of trouble:

my_delete(ptr++)

So, I think I prefer the non-macro way.

Mattias Nilsson
  • 3,639
  • 1
  • 22
  • 29
1

You don't

You use smart pointer like auto_ptr, shared_ptr that nulls itself.

Artyom
  • 31,019
  • 21
  • 127
  • 215