views:

312

answers:

7

So I was asked this in a recent interview, basically writing a function to combine the free and Assigning null functionality. 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 dont see why its better than what I did!!!!

+32  A: 

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
+1, most straight-forward and flexible solution.
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
Keep in mind that you would need a second version of this for arrays.
Space_C0wb0y
The question of course is: what's safe about this ? You hide bugs instead of checking them...
Matthieu M.
@Matthieu M: First, you need to prove that this is only useful for hiding bugs.
SigTerm
@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.
[...] 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.
@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.
@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
@SigTerm: I agree to put an end to the discussion, we manifestly have very different opinions :)
Matthieu M.
@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
+8  A: 

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
What if they don't want shared pointer semantics? No point having that extra overhead if you don't need it.
Peter Alexander
@Peter scoped_ptr in that case which likewise provides reset.
@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
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
+1  A: 

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
+2  A: 

but I dont see why its better than what I did!!!!

When you write ptr = newdelete(ptr);, you're writing ptr twice. When you write safeDelete(i); as in SigTerm's solution, you write it once.

Alexandre C.
A: 

@Space_C0wb0y,@SigTerm How would you specialize the template safeDelete to avoid memory corruption when feed with array ?

tojas
Do you know if that is an actual problem these days?I know that some compilers generate exactly the same code for `delete p` as for `delete [] p`
Mattias Nilsson
If you have not enough reputation to comment, you should ask a new question refering to this one. You'll probably get both answers and reputation score :)
ereOn
@Mattias Nilsson: Using `delete` when `delete[]` is expected is wrong. Period. You know the type of your pointer, why would you use `delete` on a array ?! And if you do so, the behavior is **undefined**.
ereOn
A: 

You don't

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

Artyom
A: 

Can someone please explain to me what exactly is following declarion

int*& a;

how can I read and understand it. Also I am unable to compile that line in gcc, it says " error: expected ‘;’, ‘,’ or ‘)’ before ‘&’ token", am I doing something wrong here or is it just not possible in C??

Harshad
Make a new question.
Ben313