当前位置:  开发笔记 > 编程语言 > 正文

在删除之前有没有理由检查NULL指针?

如何解决《在删除之前有没有理由检查NULL指针?》经验,为你挑选了4个好方法。

我经常NULL在删除指针之前看到遗留代码检查,类似于

if (NULL != pSomeObject) 
{
    delete pSomeObject;
    pSomeObject = NULL;
}

NULL在删除之前有没有理由检查指针?NULL之后设置指针的原因是什么?



1> Randolpho..:

删除空指针是完全"安全的"; 它实际上相当于一个无操作.

您可能希望在删除之前检查null的原因是尝试删除空指针可能表示程序中存在错误.


@Dbger:我们开始......使用ISO/IEC 14882:2003第5.3.5节第2段,第二句:"在任何一种方法中,如果`delete`的操作数的值是空指针,则操作无效".
@Dbger:你是从谷歌代码页得到的吗?我也是.我太便宜了,无法在ISO网站上花三十块钱.这样的废话正是这些天世界的错误,IMO.
@Dbger:我不确定你的意思,所以让我澄清我的帖子中的*I*意思.如果将NULL指针传递给删除机制,是的,在掩盖下,进行空检查,如果指针为空,则"函数"只返回而不实际执行任何操作.但是你可能想要在删除之前检查空指针的*reason*是,如果你试图删除已经设置为null的指针,这意味着你对指针的假设是不正确的.如果您的假设不正确,则可能存在错误.
-1请澄清你的意思"在你删除之前你可能想要检查null的原因是试图删除空指针可能表示程序中存在错误." 我没有看到如问题中的代码所示检查null如何帮助检测/避免/解决这样的错误,那么它如何有用呢?
@Randolpho谢谢你,这很有道理.关键部分是"并记录您尝试删除NULL指针的事实",这不在代码示例中,我不相信您在答案或后续评论中提到过它(尽管它可能就在那里而且我'我想念它,发生了陌生的事情.如果您在答案中添加了这个说明,那将会很有帮助; 我真的不知道你的意思.

2> Konrad Rudol..:

C++标准保证在delete-expression(§8.5.2.5/ 2)中使用空指针是合法的.但是,未指定是否将调用释放函数(operator deleteoperator delete[];§8.5.2.5/ 7,注意).

如果使用空指针调用默认的释放函数(即由标准库提供),则调用无效(第6.6.4.4.2/3节).

但是如果标准库没有提供释放函数,那么未指定会发生什么 - 即当我们重载operator delete(或operator delete[])时会发生什么.

一个称职的程序员会相应地释放函数处理空指针,而不是在调用之前处理,如OP的代码所示.同样,将指针设置为nullptr/ NULL删除后仅用于非常有限的目的.有些人喜欢以防御性编程的精神来做这件事:在出现错误的情况下,它会使程序行为更容易预测:删除后访问指针将导致空指针访问,而不是访问随机存储器位置.尽管两个操作都是未定义的行为,但是在实践中空指针访问的行为更加可预测(它通常导致直接崩溃而不是内存损坏).由于内存损坏特别难以调试,因此重置已删除的指针有助于调试.

- 当然这是治疗症状而不是病因(即病毒).您应该将重置指针视为代码气味.干净,现代的C++代码将使内存所有权清晰并静态检查(通过使用智能指针或等效机制),从而可以证明避免这种情况.

额外奖励:重载的解释operator delete:

operator delete是(尽管它的名字)一个可能像任何其他功能一样重载的函数.对于operator delete具有匹配参数的每次调用,都会在内部调用此函数.同样如此operator new.

在某些情况下,当您想要精确控制内存的分配时,重载operator new(以及然后也是operator delete有意义的)是有意义的.这样做甚至都不是很难,但必须采取一些预防措施以确保正确的行为.Scott Meyers详细描述了这个有效的C++.

现在,让我们说我们想要重载operator new调试的全局版本.在我们这样做之前,请简要注意以下代码中发生的情况:

klass* pobj = new klass;
// … use pobj.
delete pobj;

这里到底发生了什么?以上可以粗略地翻译成以下代码:

// 1st step: allocate memory
klass* pobj = static_cast(operator new(sizeof(klass)));
// 2nd step: construct object in that memory, using placement new:
new (pobj) klass();

// … use pobj.

// 3rd step: call destructor on pobj:
pobj->~klass();
// 4th step: free memory
operator delete(pobj);

请注意步骤2,我们new使用稍微奇怪的语法调用.这是对所谓的放置new的调用,它接受一个地址并在该地址构造一个对象.此运算符也可能过载.在这种情况下,它只用于调用类的构造函数klass.

现在,这里没有进一步说明运算符的重载版本的代码:

void* operator new(size_t size) {
    // See Effective C++, Item 8 for an explanation.
    if (size == 0)
        size = 1;

    cerr << "Allocating " << size << " bytes of memory:";

    while (true) {
        void* ret = custom_malloc(size);

        if (ret != 0) {
            cerr << " @ " << ret << endl;
            return ret;
        }

        // Retrieve and call new handler, if available.
        new_handler handler = set_new_handler(0);
        set_new_handler(handler);

        if (handler == 0)
            throw bad_alloc();
        else
            (*handler)();
    }
}

void operator delete(void* p) {
    cerr << "Freeing pointer @ " << p << "." << endl;
    custom_free(p);
}

与大多数实现一样,此代码仅使用malloc/ freeinternal 的自定义实现.它还会创建一个调试输出.请考虑以下代码:

int main() {
    int* pi = new int(42);
    cout << *pi << endl;
    delete pi;
}

它产生了以下输出:

Allocating 4 bytes of memory: @ 0x100160
42
Freeing pointer @ 0x100160.

现在,这段代码做了一些根本不同于标准实现的东西operator delete:它没有测试空指针!编译器不会检查这一点,所以上面的代码编译,但是当你尝试删除空指针时,它可能会在运行时给出令人讨厌的错误.

但是,正如我之前所说,这种行为实际上是意外的,并且库编写者应该注意检查中的空指针operator delete.这个版本有很大的改进:

void operator delete(void* p) {
    if (p == 0) return;
    cerr << "Freeing pointer @ " << p << "." << endl;
    free(p);
}

总之,尽管草率实现operator delete可能需要在客户端代码中进行显式空检查,但这是非标准行为,并且只应在遗留支持中容忍(如果有的话).


由于重载操作符损坏而在删除前检查null是错误的 - 修复操作员!
删除指针设置为NULL还有另一个好处:保证任何后续尝试取消引用**指针会立即崩溃,而不是做谁也不知道的什么.

3> EvilTeach..:

在内部删除对NULL的检查.你的测试是多余的



4> Welbog..:

删除null是一个无操作.在调用delete之前没有理由检查null.

如果指针为null,则可能需要检查null是否存在其他原因.


+1来反击那个荒谬的-1(我希望我可以发表评论).有*确实*没有理由检查NULL,性能是*不*这样做的原因...在删除之前检查NULL是多余的,并且它是编译器无法消除的冗余.这个答案有用地包括观察到`if(p!= NULL){dosomethingwith(p);测试不是多余的.删除p; }`,这是一种常见的模式.
推荐阅读
家具销售_903
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有