所谓的代码段、数据段
一般面试C++,都会很无聊的问到虚拟函数的实现机制,接着就会问到vtable放在哪里 - 实现细节中的细节,我个人觉得这个除了卖弄没啥大意义,但面试嘛,一般就这吊样。
写个小程序:
#include <iostream> using namespace std; // .data - read-write data int rwdata = 100; // .rodata - read-only data const char* rodata = "hello, world"; // .bss - non-initialized data int bssdata; // .text void text_code() { cout << "text_code" << endl; } class VTableTest { public: virtual void virtualfunc() { cout << "virtualfunc" << endl; } }; int main() { cout << ".data: " << &rwdata << endl; cout << ".rodata: " << reinterpret_cast<const void*>(rodata) << endl; cout << ".bss: " << &bssdata << endl; cout << ".text-normal-function: " << reinterpret_cast<void*>(text_code) << endl; VTableTest* pV = new VTableTest(); long* pVlong = reinterpret_cast<long*>(pV); void* vptr = reinterpret_cast<void*>(*pVlong); cout << ".rodata-vtable: " << vptr << endl; }
编译运行:
$ segment .data: 0x804a030 .rodata: 0x80489d0 .bss: 0x804a114 .text-normal-function: 0x80486e4 .rodata-vtable: 0x8048a40
查询各个段的地址范围:
$ readelf -S segment There are 29 section headers, starting at offset 0x115c: Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 [ 1] .interp PROGBITS 08048154 000154 000013 00 A 0 0 1 [ 2] .note.ABI-tag NOTE 08048168 000168 000020 00 A 0 0 4 [ 3] .note.gnu.build-i NOTE 08048188 000188 000024 00 A 0 0 4 [ 4] .gnu.hash GNU_HASH 080481ac 0001ac 000034 04 A 5 0 4 [ 5] .dynsym DYNSYM 080481e0 0001e0 0000f0 10 A 6 1 4 [ 6] .dynstr STRTAB 080482d0 0002d0 00018e 00 A 0 0 1 [ 7] .gnu.version VERSYM 0804845e 00045e 00001e 02 A 5 0 2 [ 8] .gnu.version_r VERNEED 0804847c 00047c 000060 00 A 6 2 4 [ 9] .rel.dyn REL 080484dc 0004dc 000018 08 A 5 0 4 [10] .rel.plt REL 080484f4 0004f4 000050 08 A 5 12 4 [11] .init PROGBITS 08048544 000544 00002e 00 AX 0 0 4 [12] .plt PROGBITS 08048580 000580 0000b0 04 AX 0 0 16 [13] .text PROGBITS 08048630 000630 00037c 00 AX 0 0 16 [14] .fini PROGBITS 080489ac 0009ac 00001a 00 AX 0 0 4 [15] .rodata PROGBITS 080489c8 0009c8 000094 00 A 0 0 8 [16] .eh_frame_hdr PROGBITS 08048a5c 000a5c 00005c 00 A 0 0 4 [17] .eh_frame PROGBITS 08048ab8 000ab8 000168 00 A 0 0 4 [18] .init_array INIT_ARRAY 08049ef8 000ef8 000004 00 WA 0 0 4 [19] .ctors PROGBITS 08049efc 000efc 000008 00 WA 0 0 4 [20] .dtors PROGBITS 08049f04 000f04 000008 00 WA 0 0 4 [21] .jcr PROGBITS 08049f0c 000f0c 000004 00 WA 0 0 4 [22] .dynamic DYNAMIC 08049f10 000f10 0000e0 08 WA 6 0 4 [23] .got PROGBITS 08049ff0 000ff0 000004 04 WA 0 0 4 [24] .got.plt PROGBITS 08049ff4 000ff4 000034 04 WA 0 0 4 [25] .data PROGBITS 0804a028 001028 000010 00 WA 0 0 4 [26] .bss NOBITS 0804a040 001038 0000dc 00 WA 0 0 32 [27] .comment PROGBITS 00000000 001038 00002a 01 MS 0 0 1 [28] .shstrtab STRTAB 00000000 001062 0000f8 00 0 0 1
值得注意的是,vtable是作为readonly的data被放在.rodata段,而不是大家所认为的.text段(代码段)