我继承了一个大型 c++ 代码库,我的任务是避免代码库中可能发生的任何空指针异常。是否有可用的静态分析工具,我在想你已经成功使用的 lint。
你还注意什么?
我继承了一个大型 c++ 代码库,我的任务是避免代码库中可能发生的任何空指针异常。是否有可用的静态分析工具,我在想你已经成功使用的 lint。
你还注意什么?
您可以从消除 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 以响应错误。然后,您会在每个函数中看到大量的 NULL 检查,无论该函数多么微不足道。而且,只需要一个不检查 NULL 来使程序崩溃的地方。异常迫使您仔细考虑错误并准确决定应该在哪里以及如何处理它。
似乎您只是在寻找简单的解决方案,例如静态分析工具(您应该始终使用)。更改指向引用的指针也是一个很好的解决方案。但是,C++ 具有 RAII 的优点,它消除了到处都有“try {} finally {}”的需要,所以我认为它值得你认真考虑。
首先,作为一个技术点,C++ 没有 NULL 指针异常。取消引用 NULL 指针具有未定义的行为,并且在大多数系统上会导致程序突然终止(“崩溃”)。
至于工具,我也推荐这个问题:
特别是关于 NULL 指针取消引用,请考虑 NULL 指针取消引用具有三个主要元素:
静态分析工具的难点当然是第 2 步,而工具的区别在于它们可以准确(即,没有太多误报)跟踪的路径有多复杂。查看您想要捕获的一些特定错误示例可能会很有用,以便更好地建议哪种工具最有效。
免责声明:我为 Coverity 工作。
如果您不想更改任何代码,则必须使用一些工具(请参阅其他答案)。但是对于问题的一个特殊部分(在函数中放置一个指针来使用它)有一个很好的小 Makro-Definition 可以用来找到一些小错误:(在发布模式下没有时间开销并添加了一个可见的代码的条件)
#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:首先在这里找到,可以进一步调整
一个附带问题,避免这些的目的是因为他们不希望客户看到崩溃吗?在许多情况下,空指针是应立即处理的意外情况,但它们常常像烫手山芋一样通过系统。
我曾经在一个代码库上工作,习惯是在进入函数时首先检查任何空指针,如果是,则返回。这样做的问题是,虽然该工具没有崩溃,但它最终默默地生成了坏数据。并且尝试调试这些问题很困难,因为在结果变得无法容忍或最终不得不表现出来之前,可能已经通过许多函数非法传递了很长时间的空指针。
理想情况下,您至少在开发期间需要正确的断言,因此请考虑使用宏来隐藏或重新定义生产构建的断言