开发者

NULL check before deleting an object with an overloaded delete

开发者 https://www.devze.com 2023-01-18 14:16 出处:网络
This came up as one of the code review comments. Is it a good idea to check for NULL before calling delete for any object?

This came up as one of the code review comments.

Is it a good idea to check for NULL before calling delete for any object?

I do understand delete operator checks for NULL internally and is redundant but the argument put forth was delete as an operator can be overloaded and if the overloaded version doesn't check for th开发者_如何学编程e NULL it may crash. So is it safe and reasonable to assume that if and when delete will be overloaded it will check for the NULL or not? In my understanding its reasonable to assume the first case that overloaded delete shall take care of the NULL check, and the review point doesn't hold good. What do you think?


No, don't check for null. The standard says that delete (T*)0; is valid. It will just complicate your code for no benefits. If operator delete is overloaded it's better to check for null in the implementation of the operator. Just saves code lines and bugs.

EDIT: This answer was accepted and upvoted, yet, in my opinion, it was not very informative. There is one missing piece in all answers here, and, for conscience sake, let me add this last piece here.

The standard actually says in [basic.stc.dynamic], at least since C++03:

Any allocation and/or deallocation functions defined in a C++ program, including the default versions in the library, shall conform to the semantics specified in 3.7.4.1 and 3.7.4.2.

Where the referenced sections, as well as some other places in the standard listed in other answers, say that the semantics of passing a null pointer are a no-op.


I would say that that's more a reason to ensure that if you overload operator delete, then you should always have it check for NULL, otherwise you're breaking the semantics.


Is it a good idea to check for NULL before calling delete for any object?

No!

int *p = NULL;
delete p ; //no effect

The Standard says [Section 5.3.5/2]

If the operand has a class type, the operand is converted to a pointer type by calling the above-mentioned conversion function, and the converted operand is used in place of the original operand for the remainder of this section. In either alternative, if the value of the operand of delete is the null pointer the operation has no effect.

Furthermore in Section 18.4.1.1/13

void operator delete(void* ptr) throw();

void operator delete(void* ptr, const std::nothrow_t&) throw();

Default behavior:

For a null value of ptr, do nothing.

— Any other value of ptr shall be a value returned earlier by a call to the default operator new, which was not invalidated by an intervening call to operator delete(void*) (17.4.3.7). For such a non-null value of ptr, reclaims storage allocated by the earlier call to the default operator new.

EDIT :

James Kanze here says that

It's still the responisiblity of operator delete (or delete[]) to check; the standard doesn't guarantee that it won't be given a null pointer; the standard requires that it be a no-op if given a null pointer. Or that the implementation is allowed to call it. According to the latest draft, "The value of the first argument supplied to a deallocation function may be a null pointer value; if so, and if the deallocation function is one supplied in the standard library, the call has no effect." I'm not quite sure what the implications of that "is one supplied in the standard library" are meant to be---taken literally, since his function is not one provided by the standard library, the sentence wouldn't seem to apply. But somehow, that doesn't make sense.


I would say it is the responsibility of an overloaded delete to behave like you expect delete to behave. That is, it should handle NULL pointers as a no-op.

And so, when calling an overloaded delete, you should not check for NULL. You should rely on the overloaded delete to be implemented correctly.


No need to check null. delete operator does chck for null so additional check is not required.


delete (T*)0; is valid and does nothing, similarly free(NULL); is also valid and does nothing. If you overload the delete operator, your implementation should carry the same semantics. The standard says how the standard delete will work, but I don't think it says how an overloaded delete should behave. For the sake of consistency with the standard/default behaviour, it should allow (T*)0 as input.


From Standard docs, 18.5.1.1.13 under delete,

Default behavior: If ptr is null, does nothing. Otherwise, reclaims the storage allocated by the earlier call to operator new.

So, you don't have to check by default..


No need to check for NULL prior to deleting. If someone has overloading delete with something that does not behave in a standard way then that's the real problem. No-one should take lightly the task of overloading delete and should always support expected behaviour such as checking for NULL and taking no action.

However, for what it's worth, you should always remember to assign zero to any pointer that you've just deleted, unless for example you are about to delete the pointer as well:

void MyObj::reset()
{
    delete impl_;
    impl_ = 0;    // Needed here - impl_ may be reused / referenced.
}

MyObj::~MyObj()
{
    delete impl_; // No need to assign here as impl_ is going out of scope.
}


Is it not necesary to check. If anyone overload the pethod, is his responsibility to to whatever with NULL.


I would say the questions contains incomplete information. My shop still has a check for NULL before delete in our coding standard, as we still have one compiler/platform configuration that we must support that goes into undefined behavior with the defualt delete operator if it is passed NULL. If the original poster has a simular situation then there is a point to the check for NULL, otherwise, change the coding standard!


A bit of C++ pedantry: NULL is not a built-in concept. Yes we all know what it means but in C++ before C++0X the null pointer concept is simply the value 0. NULL is usually a platform-specific macro that expands to 0.

With C++0X we're getting nullptr which is clearer than a plain zero and is not convertible to any integral type except bool, and is a better concept than NULL (or perhaps a better implementation of the concept behind NULL).

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号