为什么用三元初始化 class 会导致双重释放?

Why does initializing a class with a ternary if cause a double-free?

在启用 clang-analyzer 的情况下使用 clang 编译以下代码时:

#include <stdlib.h>
struct Buffer {
    unsigned char *buf;
    Buffer() : buf(0) {}
    Buffer(const Buffer &that) {
        buf = new unsigned char;
        *buf = *that.buf;
    }
    Buffer(Buffer &&);
    ~Buffer() { delete buf; }
    Buffer &operator=(const Buffer &that) = delete;
    Buffer &operator=(Buffer &&that) = delete;
};

Buffer func() {
    Buffer a;
    return a;
}

int main() { Buffer a = 1 ? func() : Buffer(); }

使用命令:

scan-build clang++ main.cc -std=c++17

产生以下错误:

main.cc:10:17: warning: Attempt to free released memory
    ~Buffer() { delete buf; }

但是,当用 Buffer a = func();(没有三元 if)初始化 a 时,错误消失了。此外,使用 -std=c++11 也会使错误消失。

为什么会这样?

程序格式错误,因为使用了移动构造函数,但未定义这违反了单一定义规则。程序中的这个错误可能导致扫描仪诊断误报。

未使用复制构造函数,但它已损坏,因为它可能通过空指针进行间接访问。