【问题标题】:Uninitialized member not caught by compiler. Is it a bug?编译器未捕获未初始化的成员。它是一个错误吗?
【发布时间】:2021-06-28 09:25:00
【问题描述】:

作为一个糟糕的c++程序员,我今天遇到了这个segfault:一个未初始化的shared_ptr 给了一个NULL,我的程序崩溃了。对于普通班级成员,如果成员未初始化,我会收到警告或错误。但在这种情况下不是。我在下面制作了一个复制品。

在调试模式下,此段错误。我没有收到预期的未初始化变量的编译器错误或警告。

这是一个错误吗?还是我误会了。 编译器不应该在这段代码上发出警告或错误吗?

我根本不希望它编译!

我认为编译器应该报错,说你需要在类构造函数中初始化私有wooo...

#include <iostream>
#include <memory>
#include <vector>
using namespace std;

class Wooo{
public:
    int maybe;
    int istrue(){
        return maybe + 1;}
private:
    Wooo(); // just to be explicit about deleted default constructor
};

class Weee{
public:
    Weee(){}; // just empty constructor. reading wooo anywhere will give a NULL
    
    Wooo seg_me(){
        return *wooo.get();
    };
private:
    const std::shared_ptr<Wooo> wooo;
};

int main()
{   
    auto w = Weee();
    cout<<"Hello World\n";
    cout<< w.seg_me().istrue() << "\n";

    return 0;
}


【问题讨论】:

  • 嗯,它初始化...到nullptr。恐怕您的编译器不够聪明,无法警告您取消引用该空指针,但也许另一个静态分析器会。
  • 识别 Undefined Behavior 的实例或其他有问题的代码属于 实施质量,因为这样做的范围从微不足道到不可能甚至如果你能解决停机问题。编译器通常只是假设它不会发生,并积极修剪路径以弥补不完美的信息并实现高效的代码。在运行时留下陷阱进行识别通常会降低效率,因此沦为调试模式和低优化。
  • 可以确认,此行为被未定义的行为清理程序捕获。使用 -fsanitize=undefined 构建就像圣诞树一样点亮它

标签: c++ segmentation-fault c++17


【解决方案1】:

一个未初始化的 shared_ptr ...

我认为编译器应该报错并说你需要初始化私有的wooo

没有未初始化。它只是默认初始化的。通过其默认构造函数。致nullptr

未显式初始化的shared_ptr 等价于原始指针

Wooo *wooo = nullptr;

这是一个错误吗?

是的,这是您的代码中的一个错误:您允许指针被默认初始化,然后在实际指向某个地方之前取消引用它。


你有两种可能的情况:

  1. 绝不允许Weee::wooo 包含nullptr

    在这种情况下,错误是您编写的构造函数未能建立您的类不变量。

    你应该有

    Weee() : wooo{make_shared ...} {}
    

    和/或

    explicit Weee(shared_ptr<Wooo>&& p) : wooo{std::move(p)} {}
    

    或其他。

    关键是 如果 有一个非 nullptr 成员是一个类不变量,那么 任何 构造函数或方法可能会使这个不满足是错误的。

  2. 有时允许Weee::wooo 包含nullptr,因为您有两阶段初始化 (boo),或者因为它实际上是可选的或有条件的。

    在这种情况下,错误是您在取消引用之前没有检查指针是否(非常合法)nullptr

【讨论】:

  • 好的。这主要回答了我想知道的问题。我所期望的是编译器会看到我的错误(忘记编写正确的构造函数)如何用类型捕获这种情况?
  • 如果这是所需的行为,您可以编写一个限制为非空的智能指针,例如GSL 中的not_null。但是您仍然需要首先确定预期的语义是什么,而您还没有解决这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-14
相关资源
最近更新 更多