从参考中获取的指针可以在定义明确的C 中取无效



这个问题是由于Clang和GCC对nullptr检查指针值的不均匀处理而动机。对于this,它们都发出警告,但对于通过在对象上使用address-of操作员来保持安静的指针。

我很确定,这样的指针应该始终有效,因为我们由于现代编译器从Happy 90年代的C 代码上删除了此类检查而经历了错误。

这让我感到困扰,为什么编译器在通常的情况下保持安静。 if是否有可能触发,还是在两个主要编译器中只是一个设计决定?在我开始编写补丁程序或错误编译器开发器之前,我想确定我不是缺少一些东西。

玩具示例:

#include <iostream>
class A {
    void f(){
        if(!this) {
            std::cout << "This can't trigger, and compilers warn about it.";
        }
    }
};
void f(A& a){
    A* ptr = &a;
    if(ptr == nullptr) {
        std::cout << "Can this trigger? Because gcc and clang are silent.";
    }
}

即使问题看起来很愚蠢,我也觉得这很实际。如果一个人确实可以使用Smelly代码,则此优化的结果是致命的,因此警告将是一个非常有用的诊断。

补充此案。Clang和GCC确实知道检查具有不断的评估,因为即使对于干净的代码:

void g(A* a){
    A* ptr = a;
    if(ptr == nullptr) {
        std::cout << "Gee, can this trigger? Be cause gcc and clang are silent.";
    }
}
void g(A& a) {
    g(&a);
}

它们生成了g(A& a)中省略ifg的两个版本,因此两者都可以确定并假定参考的非删除性。GCC生成不错的可读组件:

f(A&):
        ret
.LC0:
        .string "Can this trigger? Be cause gcc and clang are silent."
g(A*):
        test    rdi, rdi
        je      .L5
        ret
.L5:
        mov     edx, 52
        mov     esi, OFFSET FLAT:.LC0
        mov     edi, OFFSET FLAT:_ZSt4cout
        jmp     std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
g(A&):
        ret

据我了解,汇编msvc /O2icc -fast将支票留在原处。

编辑:我错过了A::f()中的!,修复了它。

可以在明确定义的C ?

否。此答案中的标准报价:无效参考?

虽然,尤其是使用类型的过载的operator&服用指针的情况,可以返回任何内容,包括null。

if是否有可能触发?

不在A::f::f中。可以在g(A*)中触发,但在g(A&)调用时不会触发。

警告将是一个非常有用的诊断。

GCC和Clang不够聪明,无法在您观察到的那种情况下检测出错误,但是它们确实检测到了同一错误的更简单版本:

GCC

warning: the compiler can assume that the address of 'a' will never be NULL [-Waddress]
     if(&a == nullptr) {
        ~~~^~~~~~~~~~
warning: nonnull argument 'a' compared to NULL [-Wnonnull-compare]
     if(&a == nullptr) {
     ^~

clang

warning: reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false [-Wtautological-undefined-compare]
   if(&a == nullptr) {

相关内容

最新更新