繁体   English   中英

在大型c ++代码库中避免空指针异常

[英]Avoiding null pointer exceptions in a large c++ code base

我继承了一个大的c ++代码库,我有一个任务,以避免代码库中可能发生的任何空指针异常。 是否有可用的静态分析工具,我在想,你已经成功使用了。

你还有什么其他的东西?

您可以从消除NULL源开始:

更改

if (error) {
    return NULL;
}

if (error) {
    return DefaultObject; // Ex: an empty vector
}

如果返回的默认对象不适用且您的代码库已经使用了异常,请执行

if (error) {
    throw BadThingHappenedException;
}

然后,在适当的位置添加处理。

如果您正在使用遗留代码,您可以创建一些包装函数/类:

ResultType *new_function() {
    ResultType *result = legacy_function();
    if (result) {
        return result;
    } else {
        throw BadThingHappenedException;
    }
}

新功能应该开始使用新功能并具有适当的异常处理。

我知道一些程序员不会得到例外,包括像Joel这样的聪明人。 但是,通过返回NULL最终发生的事情是,这个NULL会像疯了一样传递,因为每个人都会认为处理它并静默返回并不是他们的事。 某些函数可能会返回错误代码,这很好,但是调用者通常最终会返回NULL-another-NULL以响应错误。 然后,无论函数多么微不足道,您都会在每个函数中看到很多NULL检查。 并且,只需要一个不检查NULL以使程序崩溃的地方。 例外情况迫使您仔细考虑错误并确定应该在何处以及如何处理错误。

您似乎只是在寻找简单的解决方案,例如静态分析工具(您应该经常使用)。 更改引用指针也是一个很好的解决方案。 但是,C ++具有RAII的优点,它无需在任何地方“尝试{}”,所以我认为值得您认真考虑。

如果你主要是维护代码库,你可以做的最低工作量和最高回报之一就是开始重构你的裸指针以引用计数指针

我还会看一些类似Purify的东西,它会检测你的代码以检测内存损坏。

首先,作为技术问题,C ++没有NULL指针异常。 取消引用NULL指针具有未定义的行为,并且在大多数系统上导致程序突然终止(“崩溃”)。

至于工具,我也推荐这个问题:

C ++静态代码分析工具是否物有所值?

特别是关于NULL指针解引用,请考虑NULL指针取消引用有三个主要元素:

  1. 引入了NULL指针。
  2. 该指针在程序中其他位置的流程。
  3. 该指针的取消引用。

静态分析工具的难点当然是步骤2,工具的区别在于它们可以准确地(即,没有太多误报)轨道的复杂路径。 查看一些您想要捕获的错误的具体示例可能会有用,以便更好地建议哪种工具最有效。

免责声明:我为Coverity工作。

如果您不想更改任何代码,则必须使用某些工具(请参阅其他答案)。 但是对于问题的一个特殊部分(你将一个指针放在一个函数中使用它),你可以使用一个很好的小Makro-Definition来找到一些小Buggers :(在发布模式下没有时间开销并添加一个可见的条件的代码)

    #ifdef  NDEBUG

    #define NotNull(X) X

    #else // in Debug-Mode

    template<typename T> class NotNull;

    template<typename T> // template specialization only for pointer-types
    class NotNull<T*> {
    public:
        NotNull(T* object)
        : _object(object) {
            assert(object);
        }

        operator T*() const {
            return _object;
        }

        T* operator->() const {
            return _object;
        }
    private:
        T *_object;
    };

    #define NotNull(X) NotNull<X>

    #endif // in Debug-Mode

您只需更改此功能:

void increase(int* counter)  
{ .. } 

对此

void increase(NotNull(int*) counter)
{ .. }  

ps:首先在这里找到了,可以进一步调整

这些可能是有趣的:

有哪些开源C ++静态分析工具?

Windows上的C ++静态代码分析工具

C ++静态代码分析工具是否物有所值?

我还会看一下使用像Valgrind这样的动态运行时工具(免费)

一个侧面问题,是避免这些的目的,因为他们不希望客户看到崩溃? 在许多情况下,空指针是应该立即处理的意外情况,但是它们常常像热土豆一样通过系统传递。

我曾经在一个代码库上工作,习惯是在进入函数时,首先检查是否有任何空指针,如果是,则返回。 这个问题是当工具没有崩溃时,它最终会无声地生成坏数据。 并且尝试调试这些问题很困难,因为在结果变得无法容忍或最终不得不表现出来之前,可能已经有很长时间通过许多函数传递了非法的空指针。

理想情况下,您至少在开发期间需要适当的断言,因此请考虑使用宏来隐藏或重新定义生成构建的断言

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM