带有函数的结构的c ++大小

时间:2017-12-09 02:31:56

标签: c++ struct sizeof

结果显示12 函数foobar在哪里存储在内存中?

#include <iostream>
using namespace std;
struct ABC_ {
    int a;
    int b;
    int c;
    int foobar(int a) {
        return a;
    }
};
int main() {
    ABC_ ABC;
    cout << sizeof ABC;
    return 0;
}

4 个答案:

答案 0 :(得分:3)

函数foobar不是对象的一部分。相反,它是已编译程序的一部分。调用该函数时,机器代码引用其地址。

答案 1 :(得分:3)

sizeof()将仅考虑成员变量。

此外,非vptr方法对struct的大小没有贡献,因为它们不需要任何运行时支持。

您的struct

类似
struct ABC_ {
    int a;
    int b;
    int c;
};
int ABC_::foobar(int a) {
    return a;
}

答案 2 :(得分:3)

该功能存储在.text段内。

  

编译程序的内存分为五个部分:文本,   数据,bss,堆和堆栈。每个细分代表一个特殊部分   为某种目的而留出的记忆。文本段是   有时也称为代码段。这是组装的地方   该程序的机器语言指令位于。

对象本身的内存布局是:

class ABC_ {
public:
    int a; // 0x4 (4)
    int b; // 0x8 (8)
    int c; // 0xC (12)
    int foobar(int a) { // you can print address using &foobar
        return a;
    }
};

当你的类包含虚函数时,它们以相同的方式存储,但你的类的内存布局发生了变化......它将有一个不可见的4字节(32位)指向虚函数表或虚方法的指针table / VMT (这个表只保存允许多态的函数的地址,这样的表是为每个类分别创建的,当它继承另一个表存储在内存中)所以在这种情况下,大小将是16.它还取决于编译器的对齐设置......

如果你想获得指向vtable的指针,你可以这样做:

void **get_vtable(void *obj) {
    return *(void ***)obj;
}

Vtable通常存储在我知道的每个编译器的开头。

你可以注意到功能是虚拟的,而不是通过查看它被调用的方式。正常函数直接调用/ jmped但是虚函数,它们由存储在表中的函数指针调用。

(某些x86 asm在我的脑海里,可能是错的)

mov edx, [ecx] // ecx = this pointer
add edx, 12h // let's say 0x12 is the offset divided by 4 is 4 = index in vtable
call edx // you know it's virtual function

或只是

mov edx, [ecx+12h]
call edx

了解内存如何存储在内存中的最佳方法是使用一些反汇编程序和/或调试程序。我推荐IDA Pro和x64dbg。

答案 3 :(得分:2)

添加到现有答案:

另外值得注意的是,使用虚方法的类大8个字节(或者系统上的指针有多少个字节)。这是一个指向具有虚拟方法地址的表的指针。这是程序在运行时知道要调用哪个版本的虚拟方法。