【发布时间】:2021-10-06 22:31:31
【问题描述】:
首先,我知道在空指针上调用方法是未定义的行为。我也知道,因为这不应该发生,编译器可以(并且确实)假设this 始终为非空。
但在实际代码中,您有时会意外地这样做。通常,它没有不良影响,当然this在方法中为null,并且事情可能会崩溃。
作为调试辅助,本着及早崩溃的精神,我将assert(this != 0) 放入了一个我之前不小心调用了几次空指针的方法中。它似乎有效,但clang抱怨:
warning: 'this' pointer cannot be null in well-defined C++ code; comparison may be
assumed to always evaluate to true [-Wtautological-undefined-compare]
assert (this ! = 0);
^~~~ ~
我想知道检测this 是否为空的最佳(最不正确)方法是什么。可以优化一个简单的比较。
- 我可以对
this做一些指针运算来试图欺骗编译器,或者强制它把指针当作一个整数来处理。 - 我可以使用
memcmp。 - 也许有特定于编译器的扩展说“不要优化这个表达式”?
另外一个问题是,在继承的情况下,“null”这个指针实际上可能类似于0x00000004,所以最好也处理这种情况。我对 Clang、MSVC 或 GCC 的解决方案感兴趣。
【问题讨论】:
-
“作为调试辅助,本着尽早崩溃的精神”,您应该使用 GCC 和 clang 现在支持的各种
-fsanitize选项进行编译。您应该使用assert获得您所追求的效果,而无需修改您的代码。这并不能回答您的实际问题,但我怀疑您的实际问题没有答案。 -
在 C++ 中检查指针是否为空的标准方法是 myptr == nullptr;我不知道这是否与 NULL 或 0 不同,但无论如何这是一个常见的检查,例如在进行动态转换以查看它是否成功之后,所以我不认为编译器应该优化它,因为它是非常重要的检查。
-
@TitoneMaurice 当编译器可以在编译时证明比较永远不会为真时,编译器优化与
nullptr的比较是有意义的。这就是编译器真正做的事情。 -
请注意
assert是一个宏,仅当NDEBUG未定义时才有效。大多数 IDE 为发布版本设置了NDEBUG,因此除非您使用使用assert的调试版本进行全面测试,否则可能无法捕获所有情况。此外,向每个成员函数添加这样的断言并不是 IMO 的好主意。而是尝试添加可以捕获此类错误的综合单元测试(最好不需要assert)。 -
@DragonRock 啊,刚刚做了一个测试,对空指针的方法调用实际上适用于我的编译器。嗯。不知道那个。本来以为在空指针上调用方法会导致运行时错误,但是,是的,既然我这样做了,当然,从编译器的角度来看,对象只是内存中的一些数据。我的错。