3

The result says 12.
Where is the function foobar stored in the memory?

#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;
}
Peter Hwang
  • 971
  • 1
  • 12
  • 25
  • 1
    Here is a good book to learn more about object model: https://www.amazon.com/Inside-Object-Model-Stanley-Lippman/dp/0201834545 – Chen Li Dec 09 '17 at 02:53

4 Answers4

5

The function is stored inside .text segment.

A compiled program’s memory is divided into five segments: text, data, bss, heap, and stack. Each segment represents a special portion of memory that is set aside for a certain purpose. The text segment is also sometimes called the code segment. This is where the assembled machine language instructions of the program are located.

The memory layout of the object itself is:

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;
    }
};

When your class contains virtual functions they're stored in the same way but memory layout of your class changes... it will have one invisible 4 byte(on 32 bit) pointer to the virtual function table or virtual method table/ VMT (this table simply holds addresses of the functions to allow polymorphism, such table is created for each class separately, when it inherits another table is stored in memory) so in that case the size would be 16. It also depends on alignment setting of the compiler...

If you want to get pointer to a vtable you can do it this way:

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

Vtable is usually stored at the beginning in every compiler I know.

You can notice the difference when function is virtual and when not by looking at the way it's called. Normal functions are directly called/jmped but virtual ones, they're called by function pointer stored in their table.

(some x86 asm out of my mind, could be wrong)

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

or simply

mov edx, [ecx+12h]
call edx

The best way to learn how things are stored in memory is to use some disassembler and/or debugger. I recommend IDA Pro and x64dbg.

Konrad
  • 6,385
  • 12
  • 53
  • 96
4

The function foobar is not part of the object. Rather, it is part of the compiled program. When the function is called, the machine code refers to its address.

Del
  • 1,309
  • 8
  • 21
3

sizeof() will consider only member variables.

Also, non-vptr methods do not contribute to the size of struct since they do not require any runtime support.

Your struct is similar to

struct ABC_ {
    int a;
    int b;
    int c;
};
int ABC_::foobar(int a) {
    return a;
}
SegFault
  • 2,526
  • 4
  • 21
  • 41
2

Adding to the existing answer:

Also interesting to note is that classes with virtual methods are 8 bytes larger (or however many bytes a pointer on your system has). This is a pointer to a table with addresses for the virtual methods. This is how the program knows at runtime which version of the virtual method to call.

Cris Luengo
  • 55,762
  • 10
  • 62
  • 120
  • 1
    Addition: vptr is put at the head of the class/struct's layout implicitly in most implementations. – Chen Li Dec 09 '17 at 03:07