强制允许取消引用NULL指针

8 c++ null-pointer undefined-behavior dereference clang++

我有一个非常古老的(和巨大的)Win32项目,该项目使用NULL指针进行大量检查,通过强制转换为指向解除引用的指针.像这样:

int* x = NULL; //somewhere
//... code
if (NULL == &(*(int*)x) //somewhere else
    return;
Run Code Online (Sandbox Code Playgroud)

是的,我知道这段代码很愚蠢,需要重构.但由于代码量很大,这是不可能的.现在我需要在Xcode的MacOS Sierra下编译这个项目,这会导致很大的问题......事实证明,在发布模式下(使用代码优化),条件以不正确的行为执行(因为解除引用NULL而被称为未定义的行为指针).

根据GCC的这个文档,有一个选项-fno-delete-null-pointer-checks,但是当启用O1,O2或O3优化时,它似乎不适用于LLVM.所以问题是:如何强制LLVM 8.0编译器允许这样的解引用?

UPDATE.检查问题的真实工作示例.

//somewhere 1
class carr
{
public:
    carr(int length)
    {
        xarr = new void*[length];

        for (int i = 0; i < length; i++)
            xarr[i] = NULL;
    }

    //some other fields and methods

    void** xarr;
    int& operator[](int i)
    {
        return *(int*)xarr[i];
    }
};

//somewhere 2
carr m(5);

bool something(int i)
{
    int* el = &m[i];
    if (el == NULL)
        return FALSE; //executes in debug mode (no optimization)

    //other code
    return TRUE; //executes in release mode (optimization enabled)
}
Run Code Online (Sandbox Code Playgroud)

-O0-O1,something保持空检查,代码"工作":

something(int):                          # @something(int)
    pushq   %rax
    movl    %edi, %eax
    movl    $m, %edi
    movl    %eax, %esi
    callq   carr::operator[](int)
    movb    $1, %al
    popq    %rcx
    retq
Run Code Online (Sandbox Code Playgroud)

-O2除此之外,检查已经过优化:

something(int):                          # @something(int)
    movb    $1, %al
    retq
Run Code Online (Sandbox Code Playgroud)

Mal*_*ean 0

对 NULL 进行基于文本的搜索。然后以警告模式运行编译器,并将所有警告打印在纸上(如果你还有这样的技术的话)。现在对于每个空值,它是有问题的空值还是好的空值?如果有问题,请将其重命名为 XNULL。

现在,C++ 检查可能会在安装了 640k 的小型系统上失败,因为 640k 对于任何人来说都足够了,但在拥有许多 GB 的现代系统上则不然。因此,重新贴上标签后,只需将它们剔除即可。如果不是这样的话。使 XNULL 成为 C++ 眼中具有有效地址的“虚拟对象”。

(从这个例子来看,代码看起来像是一个 Lisp 解释器。Lisp 需要一个空指针和一个虚拟指针,没有其他简单的方法来编写解释器)。