RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 785134
Accepted
yrHeTateJlb
yrHeTateJlb
Asked:2020-02-14 21:42:12 +0000 UTC2020-02-14 21:42:12 +0000 UTC 2020-02-14 21:42:12 +0000 UTC

在空指针处调用方法

  • 772

今天又发生了与同事的争执。他们认为这样的代码没有问题,并且在任何地方都可以正常工作:

#include <iostream>

struct S{
    int a;
    void foo(){
        std::cout << "hello";
    }
};

int main(){
    S *p = nullptr;
    p->foo();  //hello
}

他们说我们不访问数据 => 我们没有爬入地址 0 的内存 => 没有问题。我用嘴巴向他们证明,如果你调用任何非静态方法,nullptr这将立即成为未定义的行为,在这个方法中发生什么并不重要。

问题:

  • 谁是对的?
  • 它在标准中写在哪里?
  • 标准中是否有关于如何实施的内容this?
c++
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Best Answer
    AnT stands with Russia
    2020-02-14T22:26:58Z2020-02-14T22:26:58Z

    在“经典”C++ (C++98) 中,情况是明确的——取消引用空指针会导致未定义的行为。因此,通过空指针调用对象的非静态方法会导致未定义的行为。此方法是否访问类成员都没有关系。这是语言规范的立场。从这个角度来看,你是绝对正确的,你的对手关于“一切都将在任何地方工作”这个话题的论点只不过是“街头教​​育”类别中“我看汇编程序书,我明白了”的结果无花果。”

    同时,在这个问题上,为了形成更灵活/更精细的规范,已经进行了相当长的一段时间的尝试。尤其是

    DR#232:是否通过空指针进行间接未定义行为?

    然而,这方面的工作自 2005 年以来一直处于起草状态。老实说,似乎没有人可以对当前标准的文本对这个话题给出任何可以理解的解释,也许正是因为这个话题仍然“悬而未决”。

    如您所知,该标准不会为您的特定情况创建单独的规范。一旦我们转向更一般的情况,那么this在[多重]继承的条件下调用方法时立即出现诸如指针转换之类的情况。

    struct A 
    {
      int a; 
    };
    
    struct B { 
      int b; 
    
      void foo() 
      {
        // К данным мы не обращаемся
        // Но чему здесь равно `this`???
        if (this == nullptr)
          ; // ???
      }
    };
    
    struct C : A, B
    {
    };
    
    int main()
    {
      C *c = nullptr;
      c->foo();
    }
    

    不清楚编译器this在调用基类方法的过程中转换指针时是否必须遵守“null转为null”的规则?正是由于这些微妙之处,最初做出的决定是禁止通过空指针调用非静态方法。现在将会(和现在)什么以及该语言的作者的意图是什么 - 我们必须等待并弄清楚。

    请注意,顺便说一下,8.5.1.2/4要求调用类方法时的隐藏参数使用显式类型转换this进行初始化。也就是说,在上面的多重继承示例中,调用中的类型指针必须初始化为. 此转换根据 null 到 null 规则进行,结果也将是一个空指针。但是,在调用时内部的 GCC 和 Clang中, . 也就是说,这些编译器不符合 8.5.1.2/4 的要求。这立即表明 GCC 和 Clang 仍将此类调用视为未定义行为。c->foo()thisB(B *) c(B *) cthisfoo0x4

    PS 同时,在 C 语言中,空指针的解引用是被严格禁止的。

    • 7
  2. Anton Shchyrov
    2020-02-14T21:59:27Z2020-02-14T21:59:27Z

    编码

    struct S{
        int a;
        void foo(){
            std::cout << "hello";
        }
    };
    

    与此相同

    void foo(s * this){
        std::cout << "hello";
    }
    

    所以打电话

    S *p = nullptr;
    p->foo();  //hello
    

    相当于这个

    foo(nullptr)
    

    要检查,只需查看 CPU 窗口。两个调用将生成相同的代码

    mov eax, 0
    push eax
    call foo
    

    那些。只要你不解决this就没有问题。调用this将在两种情况下发生

    1. 您引用特定字段(甚至可能来自其他方法)
    2. 您将调用一个虚函数,程序将爬升以通过空指针读取 VMT

    this指针根本不传递给静态函数。

    • 2

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    是否可以在 C++ 中继承类 <---> 结构?

    • 2 个回答
  • Marko Smith

    这种神经网络架构适合文本分类吗?

    • 1 个回答
  • Marko Smith

    为什么分配的工作方式不同?

    • 3 个回答
  • Marko Smith

    控制台中的光标坐标

    • 1 个回答
  • Marko Smith

    如何在 C++ 中删除类的实例?

    • 4 个回答
  • Marko Smith

    点是否属于线段的问题

    • 2 个回答
  • Marko Smith

    json结构错误

    • 1 个回答
  • Marko Smith

    ServiceWorker 中的“获取”事件

    • 1 个回答
  • Marko Smith

    c ++控制台应用程序exe文件[重复]

    • 1 个回答
  • Marko Smith

    按多列从sql表中选择

    • 1 个回答
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Suvitruf - Andrei Apanasik 什么是空? 2020-08-21 01:48:09 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5