- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我们如何使用 objdump 实用程序和反汇编代码知道 VTABLEs(即相应的 vptr)的地址。vptr 通常存储在对象的第一个字节中。(更正/编辑此)。有一个使用虚函数的简单代码:
class base
{
public:
int x;
virtual void func()
{
//test function
}
};
class der : public base
{
void func()
{
//test function
}
};
/*
*
*/
int main() {
int s = 9;
base b;
der d ;
std::cout<<"the address of Vptr is = "<<(&b+0)<<std::endl;
std::cout<<"the value at Vptr is = "<<(int*)*(int*)((&b+0))<<std::endl;
return 0;
}
以下是代码的输出:
the address of Vptr is = 0x7fff86a78fe0
the value at Vptr is = **0x400c30**
以下是主要功能的一部分-代码的反汇编:
base b;
4009b4: 48 8d 45 d0 lea -0x30(%rbp),%rax
4009b8: 48 89 c7 mov %rax,%rdi
4009bb: e8 f4 00 00 00 callq 400ab4 <_ZN4baseC1Ev>
der d ;
4009c0: 48 8d 45 c0 lea -0x40(%rbp),%rax
4009c4: 48 89 c7 mov %rax,%rdi
4009c7: e8 fe 00 00 00 callq 400aca <_ZN3derC1Ev>
这里显示_ZN4baseC1Ev是基础对象的地址,_ZN3derC1Ev是派生对象的地址。
在 _ZN4baseC1Ev
0000000000400ab4 <_ZN4baseC1Ev>:
400ab4: 55 push %rbp
400ab5: 48 89 e5 mov %rsp,%rbp
400ab8: 48 89 7d f8 mov %rdi,-0x8(%rbp)
400abc: 48 8b 45 f8 mov -0x8(%rbp),%rax
400ac0: 48 c7 00 30 0c 40 00 movq $0x400c30,(%rax)
400ac7: c9 leaveq
400ac8: c3 retq
400ac9: 90 nop
0000000000400aca <_ZN3derC1Ev>:
}
#include<iostream>
class base
{
public:
int x;
virtual void func()
400a8a: 55 push %rbp
400a8b: 48 89 e5 mov %rsp,%rbp
400a8e: 48 89 7d f8 mov %rdi,-0x8(%rbp)
{
//test function
}
400a92: c9 leaveq
400a93: c3 retq
0000000000400a94 <_ZN3der4funcEv>:
};
class der : public base
{
void func()
400a94: 55 push %rbp
400a95: 48 89 e5 mov %rsp,%rbp
400a98: 48 89 7d f8 mov %rdi,-0x8(%rbp)
{
//test function
}
400a9c: c9 leaveq
400a9d: c3 retq
0000000000400a9e <_ZN4baseC2Ev>:
*/
#include <stdlib.h>
#include<iostream>
class base
{
400a9e: 55 push %rbp
400a9f: 48 89 e5 mov %rsp,%rbp
400aa2: 48 89 7d f8 mov %rdi,-0x8(%rbp)
400aa6: 48 8b 45 f8 mov -0x8(%rbp),%rax
400aaa: 48 c7 00 50 0c 40 00 movq $0x400c50,(%rax)
400ab1: c9 leaveq
400ab2: c3 retq
400ab3: 90 nop
0000000000400ab4 <_ZN4baseC1Ev>:
400ab4: 55 push %rbp
400ab5: 48 89 e5 mov %rsp,%rbp
400ab8: 48 89 7d f8 mov %rdi,-0x8(%rbp)
400abc: 48 8b 45 f8 mov -0x8(%rbp),%rax
400ac0: 48 c7 00 50 0c 40 00 movq $0x400c50,(%rax)
400ac7: c9 leaveq
400ac8: c3 retq
400ac9: 90 nop
0000000000400aca <_ZN3derC1Ev>:
}
};
这是 objdump 输出的链接-S exe文件
还有 objdump -t virtualfunctionsize | grep vtable 给出了这个:
0000000000400c40 w O .rodata 0000000000000018 vtable for base
0000000000601e00 g O .dtors 0000000000000000 .hidden __DTOR_END__
0000000000400b00 g F .text 0000000000000089 __libc_csu_init
0000000000400c20 w O .rodata 0000000000000018 vtable for der
我想知道- 它是什么 VTABLE 地址和它表示的相应虚函数。
Vptr 的地址 = 0x7fff86a78fe0,这代表什么 - VTABLE 位置?
Vptr 的值 = 0x400c30 - 这代表什么 - 基类的第一个虚函数?
如何找到派生类的虚函数的后续地址?
Rgds,柔软的
最佳答案
Gcc 遵循这个 C++ ABI:http://refspecs.linuxbase.org/cxxabi-1.83.html#vtable
要查看gcc生成的vtable,可以用“gcc -S”编译生成汇编源码,然后通过c++filt过滤
可以看到生成了如下虚表:
.type vtable for base, @object
.size vtable for base, 24
vtable for base:
.quad 0
.quad typeinfo for base
.quad base::func()
您可以看到前两个 8 字节的值是零(这是到顶部的偏移量,派生类在基类中的偏移量),并且是指向类型信息的指针。然后真正的 vtable(指向虚函数的指针)开始。这就是您在调试输出中看到的 vptr 值。这解释了 +0x10 偏移量。
关于c++ - 从 Objdump 实用程序检索 vptr(指向虚拟表又名 VTABLE 的指针)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10549311/
我正在阅读 Inside C++ Object Model 一书中与对象破坏相关的主题并遇到了这个问题。 它表示在执行用户自定义析构函数之前,析构函数将被扩充。扩充的第一步是将 vptr 指针重置为该
在许多资料中,书籍等都写着“不要在子类构造函数中调用 this->virtualFunction”,并且在一些资料中解释了为什么你不能这样做。因为目前根本没有创建构造类。因此,将从子构造函数调用的虚函
我有一个带有虚拟析构函数的类“base”,因此其中有一个 VTable 和相应的 VTPR,以及一个从它派生的类: class base { public: virtual ~base() {
为什么我们不对非虚函数使用相同的方法? 我的意思是,为什么我们要那样使用虚函数?我们不能将它们用作非虚拟的并覆盖它们吗? 如果这种方法可以节省我们的时间/空间或其他任何东西,为什么我们不对非虚函数使用
vptr 索引应该显示所有虚函数,但在我的例子中,3 个虚函数中只显示了 2 个。 我在下面提供完整的代码和屏幕截图:- 类头.h #include using namespace std; //
class base { public: void virtual fn(int i) { cout fn(i); cout fn(i) 调用;没事。 我的观点是,如果
我在看 this article ,它说“进入基类析构函数后,该对象成为基类对象,并且 C++ 的所有部分——虚函数、dynamic_casts 等——都以这种方式对待它。”这是否意味着 vptr 在
这与之前的许多问题类似,但它提出了一些我无法找到答案的问题。 #include using namespace std; class Base1 { public: int
最近,我一直在阅读“inside the c++ object model”。它说 vptr 在调用基类的构造函数后初始化。所以我进行了测试: class A { public: A(int
以上是一道面试题。 据我了解,作为虚拟分派(dispatch)机制的一部分,编译器会为每个类创建一个vTable,并在编译期间插入一个额外的指针(vptr)。但是它究竟是什么时候将类的虚拟表分配给这个
在c++中,我们在每个对象中都有VPTR,但每个类只有一个VTABLE。为什么 VPTR 在每个对象中?是不是重复了? 最佳答案 如果没有运行时类型信息,您将不知道对象属于哪个类。因此,为了调用方法,
有些东西我还是不明白。 对于我声明的每个类,都有一个指向类虚拟表的隐藏 vptr 成员。 假设我有这个声明: class BASE { virtual_table* vptr; //that'
根据 MSDN,__RTDynamicCast() function用于在 Visual C++ 中实现 dynamic_cast。它的参数之一是 LONG VfDelta,它被描述为“对象中虚函数指
任何具有虚函数的类都会获得一个额外的隐藏指针,该指针将指向最派生的类。 这个vptr的类型是什么? 最佳答案 它没有类型。这是标准未指定的实现细节; 它不是语言的一部分。 请注意,C++ 根本没有说必
我想知道是否存在编译器不需要将 vptr 分配给实例化对象的可能优化,即使该对象的类型是具有虚方法的类。 例如考虑: #include struct FooBase { virtual void
我正在上计算机安全课并且正在阅读 http://phrack.org/issues/56/8.html .在 bo3.cpp 中,作者创建了他自己的 VTABLE,并覆盖 VPTR 以指向他的 VTA
我有几个类(class),我试图了解 vptr 和 vtable 在这种情况下是如何工作的。 class RGB { short value[3]; }; class AbstractImage{
我想知道为什么在此处的一种情况下我在 delete 部分得到异常,而在另一种情况下却没有。 没有异常(exception)情况 #include using namespace std; class
对于一些编译器,如果一个类有虚函数,那么它的 vptr 可以用它的对象的第一个字节的地址来访问。例如, class Base{ public: virtual void f(){cout<<"
这个问题不是关于 C++ 语言本身(即不是关于标准),而是关于如何调用编译器来实现虚函数的替代方案。 实现虚函数的一般方案是使用指向指针表的指针。 class Base { private:
我是一名优秀的程序员,十分优秀!