【问题标题】:Exchangability of pointers to member function between different address spaces指向成员函数的指针在不同地址空间之间的可交换性
【发布时间】:2014-03-14 12:24:44
【问题描述】:

在 Bjarne Stroustrup 的《C++ 编程语言》中,据说可以在不同的地址空间之间传递指向虚拟成员函数的指针。

因为指向虚拟成员的指针是一种偏移量,它不依赖于 对象在内存中的位置。因此,指向虚拟成员的指针可以是 只要使用相同的对象布局,就可以在不同的地址空间之间传递 同时。像指向普通函数的指针,指向非虚函数的指针 不能在地址空间之间交换。

但是,我不明白为什么指向非虚拟函数的指针不能。就像指向虚函数的指针一样,它也像 Bjarne Stroustrup 指出的那样充当索引。

然而,一个指向成员的指针并不是一个指向一块内存的指针。 是指向变量的指针还是指向函数的指针。它更像是一个偏移量 放入结构或索引到数组中,但当然是实现 考虑到数据成员、虚函数之间的差异, 非虚函数等

我当然明白虚函数和非虚函数如vtbl等的区别。但是,在类的每次实例化时,并不像在内存上重新分配相同的成员函数,这意味着我们无法根据对象的内存地址计算成员函数的内存位置。换句话说,非虚函数不依赖于对象在内存中的位置。我认为只有一个接口(=函数)和许多对象(=也许表示)。如果指向非虚函数的指针只是成员函数之间的标识符,那么它不能在进程之间传递和使用是没有意义的。

【问题讨论】:

  • 常规方法:this 传入ECX 的函数,以固定地址调用。伪代码:func3(&obj);
  • 虚拟方法:带有this 的函数在ECX 中传递,通过vftable 取消引用调用。 vftable 指针是对象的一部分。伪代码:obj->vftable->func3(&obj);func3 基本上只是这里的静态偏移量,而不是全局内存地址。

标签: c++ pointers


【解决方案1】:

就像指向虚函数的指针一样,它也像 Bjarne Stroustrup 指出的那样充当索引。

是的,但是相对于什么的索引?指向非虚拟函数的指针是进程地址空间的索引。该函数可以在不同的进程中位于不同的地址,因此具有不同的索引。在一个进程中指向给定函数的指针(只是一个内存地址)可能指向另一个进程中完全不同的东西。

指向虚函数的指针是相对于对象地址的偏移量,因此给定一个对象(在任何进程自己的地址空间中),您可以通过应用偏移量来找到虚函数到 vtbl 条目。对象将位于不同进程中的不同地址(甚至一个进程中不同实例的不同地址),但到 vtbl 的偏移量是固定的。

换句话说,非虚函数不依赖于对象在内存中的位置。

没错,这就是问题所在!它们取决于函数在内存中的位置,这在进程之间不是恒定的。

我认为只有一个接口(=函数)和许多对象(=可能表示)。

没错。

如果指向非虚函数的指针只是成员函数之间的标识符,那么它不能在进程之间传递和使用是没有意义的。

但它们不会“像一个标识符一样”......它们是指针。它们是内存中的地址。如果函数在一个进程中的地址为 0x12341234,而在另一个进程中的地址为 0x00011234,则不能在进程之间传递指针,它不会指向同一个东西!

【讨论】:

  • 由于第二个引用,我什至没有尝试将指向成员函数的指针视为普通指针:-(
  • 非常感谢您提供如此详细的解释。
  • 指向非虚拟成员的指针不是只是指针(它有一个更大的sizeof作为开始)但它的第一个组件只是一个函数指针.对于许多平台上使用的 Itanium ABI,请参阅Member pointers
【解决方案2】:

在第二个引用中,当他谈到指向成员的指针是偏移量时,这不包括指向非虚拟成员函数的指针。这些通常作为函数代码的地址实现,因此它们不太可能在具有自己地址空间的另一个进程中工作。

【讨论】:

  • 是的。这正是我搞砸的地方。谢谢!
【解决方案3】:

一个非虚函数像一个非成员函数一样被调用,只是多了一个隐藏的this 参数。指向 1 的指针将包含要调用的函数的地址 - 任何额外的间接级别都是不必要的,并且会减慢函数调用并使程序膨胀。

通过在与对象关联的表中查找地址来调用虚函数,其内容取决于动态类型。指向一个的指针将包含该表的索引。它不能存储任何特定函数的地址:它可能引用一个基类成员,该成员被不同的派生类以不同方式覆盖,因此只有通过虚拟查找才能知道正确的覆盖。

【讨论】:

    【解决方案4】:

    像 Bjarne 一样思考。提示,他很喜欢表演。他想要他能达到的所有速度。

    如果您有一个非虚拟方法,您想立即调用该方法。任何间接都会减慢速度。虚方法内置了一些间接方法。它需要使用this 和偏移量来查找它所在的特定类型的对象,如果不需要,C++ 将绕过它。在非虚拟函数中,它不是必需的,并且为了性能而被跳过。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-27
      • 2018-04-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多