C++ 在生成的 ELF 文件中的什么地方保存它的 class 变量?
Where does C++ keep it's class variables in the resulting ELF file?
此问题具体涉及 x86 架构、g++
编译器和 c++
代码。
所以,我有以下代码:
#include <iostream>
int second;
class First {
private:
int hello;
public:
First(int number)
{
hello = number;
}
void printStuff()
{
std::cout<<this->hello<<'\n';
}
};
int main(int argc, char** argv)
{
First *first = new First(argc);
first->printStuff();
second = argc;
return 0;
}
像这样编译后:
g++ -O0 -g class.cpp -o class
我得到输出 class
二进制。
现在,我想知道 hello
存储在哪里,所以我执行 readelf -s ./class
并且输出是:
[ishaypeled@escorpio tmp14]$ readelf -s --wide ./class
Symbol table '.dynsym' contains 13 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSolsEi@GLIBCXX_3.4 (2)
2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitC1Ev@GLIBCXX_3.4 (2)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (3)
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit@GLIBC_2.2.5 (3)
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c@GLIBCXX_3.4 (2)
8: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable
9: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
10: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _Znwm@GLIBCXX_3.4 (2)
11: 00000000004006c0 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitD1Ev@GLIBCXX_3.4 (2)
12: 0000000000600dc0 272 OBJECT GLOBAL DEFAULT 26 _ZSt4cout@GLIBCXX_3.4 (2)
Symbol table '.symtab' contains 88 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000400200 0 SECTION LOCAL DEFAULT 1
2: 000000000040021c 0 SECTION LOCAL DEFAULT 2
3: 000000000040023c 0 SECTION LOCAL DEFAULT 3
4: 0000000000400260 0 SECTION LOCAL DEFAULT 4
5: 0000000000400288 0 SECTION LOCAL DEFAULT 5
6: 00000000004003c0 0 SECTION LOCAL DEFAULT 6
7: 0000000000400502 0 SECTION LOCAL DEFAULT 7
8: 0000000000400520 0 SECTION LOCAL DEFAULT 8
9: 0000000000400560 0 SECTION LOCAL DEFAULT 9
10: 0000000000400590 0 SECTION LOCAL DEFAULT 10
11: 0000000000400638 0 SECTION LOCAL DEFAULT 11
12: 0000000000400660 0 SECTION LOCAL DEFAULT 12
13: 00000000004006e0 0 SECTION LOCAL DEFAULT 13
14: 00000000004006f0 0 SECTION LOCAL DEFAULT 14
15: 0000000000400944 0 SECTION LOCAL DEFAULT 15
16: 0000000000400950 0 SECTION LOCAL DEFAULT 16
17: 0000000000400958 0 SECTION LOCAL DEFAULT 17
18: 00000000004009b0 0 SECTION LOCAL DEFAULT 18
19: 0000000000600b30 0 SECTION LOCAL DEFAULT 19
20: 0000000000600b40 0 SECTION LOCAL DEFAULT 20
21: 0000000000600b48 0 SECTION LOCAL DEFAULT 21
22: 0000000000600b50 0 SECTION LOCAL DEFAULT 22
23: 0000000000600d50 0 SECTION LOCAL DEFAULT 23
24: 0000000000600d58 0 SECTION LOCAL DEFAULT 24
25: 0000000000600da8 0 SECTION LOCAL DEFAULT 25
26: 0000000000600dc0 0 SECTION LOCAL DEFAULT 26
27: 0000000000000000 0 SECTION LOCAL DEFAULT 27
28: 0000000000000000 0 SECTION LOCAL DEFAULT 28
29: 0000000000000000 0 SECTION LOCAL DEFAULT 29
30: 0000000000000000 0 SECTION LOCAL DEFAULT 30
31: 0000000000000000 0 SECTION LOCAL DEFAULT 31
32: 0000000000000000 0 SECTION LOCAL DEFAULT 32
33: 0000000000000000 0 SECTION LOCAL DEFAULT 33
34: 0000000000000000 0 FILE LOCAL DEFAULT ABS init.c
35: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
36: 0000000000600b48 0 OBJECT LOCAL DEFAULT 21 __JCR_LIST__
37: 0000000000400720 0 FUNC LOCAL DEFAULT 14 deregister_tm_clones
38: 0000000000400760 0 FUNC LOCAL DEFAULT 14 register_tm_clones
39: 00000000004007a0 0 FUNC LOCAL DEFAULT 14 __do_global_dtors_aux
40: 0000000000600ed0 1 OBJECT LOCAL DEFAULT 26 completed.6938
41: 0000000000600b40 0 OBJECT LOCAL DEFAULT 20 __do_global_dtors_aux_fini_array_entry
42: 00000000004007c0 0 FUNC LOCAL DEFAULT 14 frame_dummy
43: 0000000000600b30 0 OBJECT LOCAL DEFAULT 19 __frame_dummy_init_array_entry
44: 0000000000000000 0 FILE LOCAL DEFAULT ABS class.cpp
45: 0000000000400954 1 OBJECT LOCAL DEFAULT 16 _ZStL19piecewise_construct
46: 0000000000600ed8 1 OBJECT LOCAL DEFAULT 26 _ZStL8__ioinit
47: 0000000000400835 62 FUNC LOCAL DEFAULT 14 _Z41__static_initialization_and_destruction_0ii
48: 0000000000400873 21 FUNC LOCAL DEFAULT 14 _GLOBAL__sub_I_second
49: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
50: 0000000000400b28 0 OBJECT LOCAL DEFAULT 18 __FRAME_END__
51: 0000000000600b48 0 OBJECT LOCAL DEFAULT 21 __JCR_END__
52: 0000000000000000 0 FILE LOCAL DEFAULT ABS
53: 0000000000400958 0 NOTYPE LOCAL DEFAULT 17 __GNU_EH_FRAME_HDR
54: 0000000000600d58 0 OBJECT LOCAL DEFAULT 24 _GLOBAL_OFFSET_TABLE_
55: 0000000000600b40 0 NOTYPE LOCAL DEFAULT 19 __init_array_end
56: 0000000000600b30 0 NOTYPE LOCAL DEFAULT 19 __init_array_start
57: 0000000000600b50 0 OBJECT LOCAL DEFAULT 22 _DYNAMIC
58: 0000000000600da8 0 NOTYPE WEAK DEFAULT 25 data_start
59: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSolsEi@@GLIBCXX_3.4
60: 0000000000400940 2 FUNC GLOBAL DEFAULT 14 __libc_csu_fini
61: 0000000000600ed4 4 OBJECT GLOBAL DEFAULT 26 second
62: 00000000004006f0 42 FUNC GLOBAL DEFAULT 14 _start
63: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
64: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
65: 0000000000400944 0 FUNC GLOBAL DEFAULT 15 _fini
66: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitC1Ev@@GLIBCXX_3.4
67: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_2.2.5
68: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit@@GLIBC_2.2.5
69: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c@@GLIBCXX_3.4
70: 00000000004006c0 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitD1Ev@@GLIBCXX_3.4
71: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable
72: 0000000000400950 4 OBJECT GLOBAL DEFAULT 16 _IO_stdin_used
73: 0000000000400888 23 FUNC WEAK DEFAULT 14 _ZN5FirstC1Ei
74: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
75: 0000000000600da8 0 NOTYPE GLOBAL DEFAULT 25 __data_start
76: 00000000004008a0 46 FUNC WEAK DEFAULT 14 _ZN5First10printStuffEv
77: 0000000000400888 23 FUNC WEAK DEFAULT 14 _ZN5FirstC2Ei
78: 0000000000600db8 0 OBJECT GLOBAL HIDDEN 25 __TMC_END__
79: 0000000000600dc0 272 OBJECT GLOBAL DEFAULT 26 _ZSt4cout@@GLIBCXX_3.4
80: 0000000000600db0 0 OBJECT GLOBAL HIDDEN 25 __dso_handle
81: 00000000004008d0 101 FUNC GLOBAL DEFAULT 14 __libc_csu_init
82: 0000000000600db8 0 NOTYPE GLOBAL DEFAULT 26 __bss_start
83: 0000000000600ee0 0 NOTYPE GLOBAL DEFAULT 26 _end
84: 0000000000600db8 0 NOTYPE GLOBAL DEFAULT 25 _edata
85: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _Znwm@@GLIBCXX_3.4
86: 00000000004007e6 79 FUNC GLOBAL DEFAULT 14 main
87: 0000000000400638 0 FUNC GLOBAL DEFAULT 11 _init
为了更好的可读性,我还运行这个命令:
[ishaypeled@escorpio tmp14]$ readelf -s --wide ./class | c++filt
Symbol table '.dynsym' contains 13 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::basic_ostream<char, std::char_traits<char> >::operator<<(int)@GLIBCXX_3.4 (2)
2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::ios_base::Init::Init()@GLIBCXX_3.4 (2)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (3)
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit@GLIBC_2.2.5 (3)
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char)@GLIBCXX_3.4 (2)
8: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable
9: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
10: 0000000000000000 0 FUNC GLOBAL DEFAULT UND operator new(unsigned long)@GLIBCXX_3.4 (2)
11: 00000000004006c0 0 FUNC GLOBAL DEFAULT UND std::ios_base::Init::~Init()@GLIBCXX_3.4 (2)
12: 0000000000600dc0 272 OBJECT GLOBAL DEFAULT 26 std::cout@GLIBCXX_3.4 (2)
Symbol table '.symtab' contains 88 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000400200 0 SECTION LOCAL DEFAULT 1
2: 000000000040021c 0 SECTION LOCAL DEFAULT 2
3: 000000000040023c 0 SECTION LOCAL DEFAULT 3
4: 0000000000400260 0 SECTION LOCAL DEFAULT 4
5: 0000000000400288 0 SECTION LOCAL DEFAULT 5
6: 00000000004003c0 0 SECTION LOCAL DEFAULT 6
7: 0000000000400502 0 SECTION LOCAL DEFAULT 7
8: 0000000000400520 0 SECTION LOCAL DEFAULT 8
9: 0000000000400560 0 SECTION LOCAL DEFAULT 9
10: 0000000000400590 0 SECTION LOCAL DEFAULT 10
11: 0000000000400638 0 SECTION LOCAL DEFAULT 11
12: 0000000000400660 0 SECTION LOCAL DEFAULT 12
13: 00000000004006e0 0 SECTION LOCAL DEFAULT 13
14: 00000000004006f0 0 SECTION LOCAL DEFAULT 14
15: 0000000000400944 0 SECTION LOCAL DEFAULT 15
16: 0000000000400950 0 SECTION LOCAL DEFAULT 16
17: 0000000000400958 0 SECTION LOCAL DEFAULT 17
18: 00000000004009b0 0 SECTION LOCAL DEFAULT 18
19: 0000000000600b30 0 SECTION LOCAL DEFAULT 19
20: 0000000000600b40 0 SECTION LOCAL DEFAULT 20
21: 0000000000600b48 0 SECTION LOCAL DEFAULT 21
22: 0000000000600b50 0 SECTION LOCAL DEFAULT 22
23: 0000000000600d50 0 SECTION LOCAL DEFAULT 23
24: 0000000000600d58 0 SECTION LOCAL DEFAULT 24
25: 0000000000600da8 0 SECTION LOCAL DEFAULT 25
26: 0000000000600dc0 0 SECTION LOCAL DEFAULT 26
27: 0000000000000000 0 SECTION LOCAL DEFAULT 27
28: 0000000000000000 0 SECTION LOCAL DEFAULT 28
29: 0000000000000000 0 SECTION LOCAL DEFAULT 29
30: 0000000000000000 0 SECTION LOCAL DEFAULT 30
31: 0000000000000000 0 SECTION LOCAL DEFAULT 31
32: 0000000000000000 0 SECTION LOCAL DEFAULT 32
33: 0000000000000000 0 SECTION LOCAL DEFAULT 33
34: 0000000000000000 0 FILE LOCAL DEFAULT ABS init.c
35: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
36: 0000000000600b48 0 OBJECT LOCAL DEFAULT 21 __JCR_LIST__
37: 0000000000400720 0 FUNC LOCAL DEFAULT 14 deregister_tm_clones
38: 0000000000400760 0 FUNC LOCAL DEFAULT 14 register_tm_clones
39: 00000000004007a0 0 FUNC LOCAL DEFAULT 14 __do_global_dtors_aux
40: 0000000000600ed0 1 OBJECT LOCAL DEFAULT 26 completed.6938
41: 0000000000600b40 0 OBJECT LOCAL DEFAULT 20 __do_global_dtors_aux_fini_array_entry
42: 00000000004007c0 0 FUNC LOCAL DEFAULT 14 frame_dummy
43: 0000000000600b30 0 OBJECT LOCAL DEFAULT 19 __frame_dummy_init_array_entry
44: 0000000000000000 0 FILE LOCAL DEFAULT ABS class.cpp
45: 0000000000400954 1 OBJECT LOCAL DEFAULT 16 std::piecewise_construct
46: 0000000000600ed8 1 OBJECT LOCAL DEFAULT 26 std::__ioinit
47: 0000000000400835 62 FUNC LOCAL DEFAULT 14 __static_initialization_and_destruction_0(int, int)
48: 0000000000400873 21 FUNC LOCAL DEFAULT 14 _GLOBAL__sub_I_second
49: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
50: 0000000000400b28 0 OBJECT LOCAL DEFAULT 18 __FRAME_END__
51: 0000000000600b48 0 OBJECT LOCAL DEFAULT 21 __JCR_END__
52: 0000000000000000 0 FILE LOCAL DEFAULT ABS
53: 0000000000400958 0 NOTYPE LOCAL DEFAULT 17 __GNU_EH_FRAME_HDR
54: 0000000000600d58 0 OBJECT LOCAL DEFAULT 24 _GLOBAL_OFFSET_TABLE_
55: 0000000000600b40 0 NOTYPE LOCAL DEFAULT 19 __init_array_end
56: 0000000000600b30 0 NOTYPE LOCAL DEFAULT 19 __init_array_start
57: 0000000000600b50 0 OBJECT LOCAL DEFAULT 22 _DYNAMIC
58: 0000000000600da8 0 NOTYPE WEAK DEFAULT 25 data_start
59: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::basic_ostream<char, std::char_traits<char> >::operator<<(int)@@GLIBCXX_3.4
60: 0000000000400940 2 FUNC GLOBAL DEFAULT 14 __libc_csu_fini
61: 0000000000600ed4 4 OBJECT GLOBAL DEFAULT 26 second
62: 00000000004006f0 42 FUNC GLOBAL DEFAULT 14 _start
63: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
64: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
65: 0000000000400944 0 FUNC GLOBAL DEFAULT 15 _fini
66: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::ios_base::Init::Init()@@GLIBCXX_3.4
67: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_2.2.5
68: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit@@GLIBC_2.2.5
69: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char)@@GLIBCXX_3.4
70: 00000000004006c0 0 FUNC GLOBAL DEFAULT UND std::ios_base::Init::~Init()@@GLIBCXX_3.4
71: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable
72: 0000000000400950 4 OBJECT GLOBAL DEFAULT 16 _IO_stdin_used
73: 0000000000400888 23 FUNC WEAK DEFAULT 14 First::First(int)
74: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
75: 0000000000600da8 0 NOTYPE GLOBAL DEFAULT 25 __data_start
76: 00000000004008a0 46 FUNC WEAK DEFAULT 14 First::printStuff()
77: 0000000000400888 23 FUNC WEAK DEFAULT 14 First::First(int)
78: 0000000000600db8 0 OBJECT GLOBAL HIDDEN 25 __TMC_END__
79: 0000000000600dc0 272 OBJECT GLOBAL DEFAULT 26 std::cout@@GLIBCXX_3.4
80: 0000000000600db0 0 OBJECT GLOBAL HIDDEN 25 __dso_handle
81: 00000000004008d0 101 FUNC GLOBAL DEFAULT 14 __libc_csu_init
82: 0000000000600db8 0 NOTYPE GLOBAL DEFAULT 26 __bss_start
83: 0000000000600ee0 0 NOTYPE GLOBAL DEFAULT 26 _end
84: 0000000000600db8 0 NOTYPE GLOBAL DEFAULT 25 _edata
85: 0000000000000000 0 FUNC GLOBAL DEFAULT UND operator new(unsigned long)@@GLIBCXX_3.4
86: 00000000004007e6 79 FUNC GLOBAL DEFAULT 14 main
87: 0000000000400638 0 FUNC GLOBAL DEFAULT 11 _init
我的问题是,变量first
在哪里?我在转储中没有看到这个对象!请注意,second
作为符号 61 存在。我预计 first
会被破坏,但不会完全消失...
有人吗?
您的对象 first
只是一个仅存在于堆栈中的本地对象。此类对象不存储在可执行文件的数据部分中。变量 second
不同,因为它是全局的。它与它的初始值一起存储(在你的情况下是默认值,因为你没有显式实例化它)并被定义为一个符号。
example.cpp:
class Clazz {
int x; // will live wherever the instance of Clazz is created
public:
Clazz(const std::initializer_list<int> & data) {}
Clazz() : x(13) {} // "13" is either in constructor code, or .rodata
};
// these will end in .data section
// except the list parameter {1, 2, 3}, which is const and lands in .rodata
static int localInt; // local symbol, will be in .o file only in debug info
int globalInt; // global symbol
// btw, both are initialized to 0, as they are defined in .data
static Clazz *classPtr = nullptr;
Clazz classInstance( {1, 2, 3} );
// all global symbols from .data/.rodata/.bss/.text (.code) sections
// will be visible in symbol table of executable (including the "foo" below)
// everything else defined below (except foo) is runtime allocated,
// and can't have any fixed address in symbol table, so it will not show there.
void foo(int param) { // param is either on stack or in register (ABI specific)
Clazz localVar; // localVar instance is living on the stack space
classPtr = new Clazz({});
// Instance of Clazz pointed at by classPtr lives in global heap memory
// If not released by explicit "delete classPtr;" during runtime,
// it will cause memory leak (avoid using naked pointers like this).
int localInt; // localInt lives on stack too, uninitialized = undefined value!
// On the contrary to *classPtr the localVar is released upon exiting it's scope
}
堆栈或堆实例都不在 ELF 文件中,在 ELF 文件中只有能够操作实例和创建实例的代码(在堆栈或堆上,通过将其实例化为 global/local变量,或 new
).
因此,除非您将某些类型实例化到 .data/.bss 部分(即在函数之外将其定义为该 .cpp 文件的 global/local),否则您无法确定变量将通过查看 executable.
的符号 table 来保存
在这段代码中,您只打印参数的数量,argc 是包含命令的参数数量,argv 是字符串数组,它是由 space[=10= 分隔的命令后的单词]
我认为,为了理解 readelf 的输出,我们首先需要了解一点编译器的工作原理。
基本上,编译器将 C/C++ 文件作为输出并生成一个 executable 文件,每个 C/C++ 通常由函数和变量构建。
为了进一步理解这一点,我们还需要讨论称为 "scopes" 的东西,范围基本上是代码中识别的位置 -
在我们的代码中,我们定义的对象/函数是可识别和可访问的。
例如让我们使用这段代码
#include <stdio.h>
int myGlob = 5;
int foo()
{
int a = 5;
printf("Hey this is foo -> %d\n",a + 1);
return a + 1;
}
int goo()
{
int b = 5;
printf("Hey this is goo -> %d\n",b - 1);
return b - 1;
}
int main()
{
printf("glob(%d) foo(%d) goo(%d)",myGlob,foo() - 1, goo() +1 );
return 0;
}
我们有三个函数和一个全局变量
foo
-> 其中有局部变量 a
goo
-> 其中有局部变量 b
- main -> 其中没有局部变量
- 我们还有
myGlob
这是一个全局变量
变量a
只能在foo
中访问,变量b
只能在goo
函数中访问,myGlob
只能在foo
函数中访问所有函数,但只有一个,所以 a
的范围是 foo
,b
的范围是 goo
,myGlob
的范围是整个模型,非常基本正确的?这是我们将在解释中更深入的地方。
这些函数/GLOBAL 对象中的每一个都称为符号,在编写实际代码时,您有许多模型和许多头文件相互调用和包含。编译器一次编译一个文件并为每个编译模型输出一个相应的目标文件,为了让模型识别其他模型,在每个模型上我们都包含一个叫做符号 table 的东西,它基本上是所有的集合您代码中的函数和全局变量应该可以被其他模型访问。
例如:
- 我们有
model.h
定义函数 foo
- 我们有
model.c
实现了 foo
- 我们有
othermodel.c
,其中包括 model.h
定义和实现
调用 goo
的函数 foo
现在,如果我们真的创建这样的东西,运行 阅读它,我们会看到 model.h
+ model .c
将合并为 model.o
和 othermodel.c
将生成 othermodel.o
,model.o
将在其中包含符号 foo
并且 foo
(实际代码和说明)和 othermodel.o
的实现将具有符号 goo
和 foo
但只有实现
foo
这是链接器介入的地方,当链接器需要将所有目标文件组合成一个 executable 时,它会读取哪个目标文件需要其中的哪些符号,并最终将所有文件组合成一个 executable ,我再次提醒你,符号也可能是函数和全局变量。
现在我们对符号是什么以及为什么在组合多个模型范围时使用每个符号有了更多的了解,我们可以理解为什么局部变量不应该有自己的符号
让我们回到之前的例子,在 model.o
的函数 foo
中
有一些局部变量 b
正如我们之前所说 b 只能由 foo 访问,为什么 model.o
的目标文件需要为 b
生成一个符号?除了 foo
中的代码,没有其他人可以访问该变量,那么为什么需要识别甚至知道它的存在?
现在老实说,这是对实际发生的事情的滥用,在现实生活中,局部变量保存在堆栈中,在您的指令代码中,当输入某些函数时,您的内存堆栈被手动操作以创建一些内存缓冲区保存与函数执行有关的所有局部变量和数据...所谓的缓冲区称为堆栈框架,其优点是一旦退出函数,堆栈就会被清理,并且函数会重新使用该内存和 运行 堆栈内存及其局部变量和函数元数据(例如 return 地址)与局部变量不同,全局变量如我示例中的 myGlob
或 second
在你的中保存在一个全局内存部分,所有适当的功能都可以访问它(实际上并不总是正确的,但现在让我们保持简单),并且内存的生命周期贯穿整个程序,它不会不断被重写就像堆栈内存一样,每个人都可以访问它,因此局部变量不需要符号或整个程序的生命周期。
如果你不知道,classC++/C 中的 es / structs 只是一堆不同类型的变量,在内存中按顺序排列,如果你的 class 实例是本地的,它是只是一堆局部变量一个接一个地位于堆栈内存中,编译器允许您使用一些 comfortable 名称访问这些变量,这些名称最终将被转换为偏移量,因此正如我们在前面的长文中所展示的很长的解释,你根本不应该\不会有局部变量的符号..如果你想看到你好你可以做的事情
static int hello;
这可能不会为您提供全局范围的可访问性,但却为您的变量提供了整个程序的生命周期..
无论如何希望我已经让你明白了一些事情,对不起我糟糕的英语水平:)
编辑:
顺便说一句,这绝对与您的 CPU 体系结构无关,即使您为 C++ PowerPC、MIPS 或 ARM 编译代码,它也将保持不变,唯一不同的是是实际的指令,也许是函数的地址,但这更多的是一个概念,而不是与 CPU 架构
相关
此问题具体涉及 x86 架构、g++
编译器和 c++
代码。
所以,我有以下代码:
#include <iostream>
int second;
class First {
private:
int hello;
public:
First(int number)
{
hello = number;
}
void printStuff()
{
std::cout<<this->hello<<'\n';
}
};
int main(int argc, char** argv)
{
First *first = new First(argc);
first->printStuff();
second = argc;
return 0;
}
像这样编译后:
g++ -O0 -g class.cpp -o class
我得到输出 class
二进制。
现在,我想知道 hello
存储在哪里,所以我执行 readelf -s ./class
并且输出是:
[ishaypeled@escorpio tmp14]$ readelf -s --wide ./class
Symbol table '.dynsym' contains 13 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSolsEi@GLIBCXX_3.4 (2)
2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitC1Ev@GLIBCXX_3.4 (2)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (3)
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit@GLIBC_2.2.5 (3)
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c@GLIBCXX_3.4 (2)
8: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable
9: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
10: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _Znwm@GLIBCXX_3.4 (2)
11: 00000000004006c0 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitD1Ev@GLIBCXX_3.4 (2)
12: 0000000000600dc0 272 OBJECT GLOBAL DEFAULT 26 _ZSt4cout@GLIBCXX_3.4 (2)
Symbol table '.symtab' contains 88 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000400200 0 SECTION LOCAL DEFAULT 1
2: 000000000040021c 0 SECTION LOCAL DEFAULT 2
3: 000000000040023c 0 SECTION LOCAL DEFAULT 3
4: 0000000000400260 0 SECTION LOCAL DEFAULT 4
5: 0000000000400288 0 SECTION LOCAL DEFAULT 5
6: 00000000004003c0 0 SECTION LOCAL DEFAULT 6
7: 0000000000400502 0 SECTION LOCAL DEFAULT 7
8: 0000000000400520 0 SECTION LOCAL DEFAULT 8
9: 0000000000400560 0 SECTION LOCAL DEFAULT 9
10: 0000000000400590 0 SECTION LOCAL DEFAULT 10
11: 0000000000400638 0 SECTION LOCAL DEFAULT 11
12: 0000000000400660 0 SECTION LOCAL DEFAULT 12
13: 00000000004006e0 0 SECTION LOCAL DEFAULT 13
14: 00000000004006f0 0 SECTION LOCAL DEFAULT 14
15: 0000000000400944 0 SECTION LOCAL DEFAULT 15
16: 0000000000400950 0 SECTION LOCAL DEFAULT 16
17: 0000000000400958 0 SECTION LOCAL DEFAULT 17
18: 00000000004009b0 0 SECTION LOCAL DEFAULT 18
19: 0000000000600b30 0 SECTION LOCAL DEFAULT 19
20: 0000000000600b40 0 SECTION LOCAL DEFAULT 20
21: 0000000000600b48 0 SECTION LOCAL DEFAULT 21
22: 0000000000600b50 0 SECTION LOCAL DEFAULT 22
23: 0000000000600d50 0 SECTION LOCAL DEFAULT 23
24: 0000000000600d58 0 SECTION LOCAL DEFAULT 24
25: 0000000000600da8 0 SECTION LOCAL DEFAULT 25
26: 0000000000600dc0 0 SECTION LOCAL DEFAULT 26
27: 0000000000000000 0 SECTION LOCAL DEFAULT 27
28: 0000000000000000 0 SECTION LOCAL DEFAULT 28
29: 0000000000000000 0 SECTION LOCAL DEFAULT 29
30: 0000000000000000 0 SECTION LOCAL DEFAULT 30
31: 0000000000000000 0 SECTION LOCAL DEFAULT 31
32: 0000000000000000 0 SECTION LOCAL DEFAULT 32
33: 0000000000000000 0 SECTION LOCAL DEFAULT 33
34: 0000000000000000 0 FILE LOCAL DEFAULT ABS init.c
35: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
36: 0000000000600b48 0 OBJECT LOCAL DEFAULT 21 __JCR_LIST__
37: 0000000000400720 0 FUNC LOCAL DEFAULT 14 deregister_tm_clones
38: 0000000000400760 0 FUNC LOCAL DEFAULT 14 register_tm_clones
39: 00000000004007a0 0 FUNC LOCAL DEFAULT 14 __do_global_dtors_aux
40: 0000000000600ed0 1 OBJECT LOCAL DEFAULT 26 completed.6938
41: 0000000000600b40 0 OBJECT LOCAL DEFAULT 20 __do_global_dtors_aux_fini_array_entry
42: 00000000004007c0 0 FUNC LOCAL DEFAULT 14 frame_dummy
43: 0000000000600b30 0 OBJECT LOCAL DEFAULT 19 __frame_dummy_init_array_entry
44: 0000000000000000 0 FILE LOCAL DEFAULT ABS class.cpp
45: 0000000000400954 1 OBJECT LOCAL DEFAULT 16 _ZStL19piecewise_construct
46: 0000000000600ed8 1 OBJECT LOCAL DEFAULT 26 _ZStL8__ioinit
47: 0000000000400835 62 FUNC LOCAL DEFAULT 14 _Z41__static_initialization_and_destruction_0ii
48: 0000000000400873 21 FUNC LOCAL DEFAULT 14 _GLOBAL__sub_I_second
49: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
50: 0000000000400b28 0 OBJECT LOCAL DEFAULT 18 __FRAME_END__
51: 0000000000600b48 0 OBJECT LOCAL DEFAULT 21 __JCR_END__
52: 0000000000000000 0 FILE LOCAL DEFAULT ABS
53: 0000000000400958 0 NOTYPE LOCAL DEFAULT 17 __GNU_EH_FRAME_HDR
54: 0000000000600d58 0 OBJECT LOCAL DEFAULT 24 _GLOBAL_OFFSET_TABLE_
55: 0000000000600b40 0 NOTYPE LOCAL DEFAULT 19 __init_array_end
56: 0000000000600b30 0 NOTYPE LOCAL DEFAULT 19 __init_array_start
57: 0000000000600b50 0 OBJECT LOCAL DEFAULT 22 _DYNAMIC
58: 0000000000600da8 0 NOTYPE WEAK DEFAULT 25 data_start
59: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSolsEi@@GLIBCXX_3.4
60: 0000000000400940 2 FUNC GLOBAL DEFAULT 14 __libc_csu_fini
61: 0000000000600ed4 4 OBJECT GLOBAL DEFAULT 26 second
62: 00000000004006f0 42 FUNC GLOBAL DEFAULT 14 _start
63: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
64: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
65: 0000000000400944 0 FUNC GLOBAL DEFAULT 15 _fini
66: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitC1Ev@@GLIBCXX_3.4
67: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_2.2.5
68: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit@@GLIBC_2.2.5
69: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c@@GLIBCXX_3.4
70: 00000000004006c0 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitD1Ev@@GLIBCXX_3.4
71: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable
72: 0000000000400950 4 OBJECT GLOBAL DEFAULT 16 _IO_stdin_used
73: 0000000000400888 23 FUNC WEAK DEFAULT 14 _ZN5FirstC1Ei
74: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
75: 0000000000600da8 0 NOTYPE GLOBAL DEFAULT 25 __data_start
76: 00000000004008a0 46 FUNC WEAK DEFAULT 14 _ZN5First10printStuffEv
77: 0000000000400888 23 FUNC WEAK DEFAULT 14 _ZN5FirstC2Ei
78: 0000000000600db8 0 OBJECT GLOBAL HIDDEN 25 __TMC_END__
79: 0000000000600dc0 272 OBJECT GLOBAL DEFAULT 26 _ZSt4cout@@GLIBCXX_3.4
80: 0000000000600db0 0 OBJECT GLOBAL HIDDEN 25 __dso_handle
81: 00000000004008d0 101 FUNC GLOBAL DEFAULT 14 __libc_csu_init
82: 0000000000600db8 0 NOTYPE GLOBAL DEFAULT 26 __bss_start
83: 0000000000600ee0 0 NOTYPE GLOBAL DEFAULT 26 _end
84: 0000000000600db8 0 NOTYPE GLOBAL DEFAULT 25 _edata
85: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _Znwm@@GLIBCXX_3.4
86: 00000000004007e6 79 FUNC GLOBAL DEFAULT 14 main
87: 0000000000400638 0 FUNC GLOBAL DEFAULT 11 _init
为了更好的可读性,我还运行这个命令:
[ishaypeled@escorpio tmp14]$ readelf -s --wide ./class | c++filt
Symbol table '.dynsym' contains 13 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::basic_ostream<char, std::char_traits<char> >::operator<<(int)@GLIBCXX_3.4 (2)
2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::ios_base::Init::Init()@GLIBCXX_3.4 (2)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (3)
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit@GLIBC_2.2.5 (3)
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char)@GLIBCXX_3.4 (2)
8: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable
9: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
10: 0000000000000000 0 FUNC GLOBAL DEFAULT UND operator new(unsigned long)@GLIBCXX_3.4 (2)
11: 00000000004006c0 0 FUNC GLOBAL DEFAULT UND std::ios_base::Init::~Init()@GLIBCXX_3.4 (2)
12: 0000000000600dc0 272 OBJECT GLOBAL DEFAULT 26 std::cout@GLIBCXX_3.4 (2)
Symbol table '.symtab' contains 88 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000400200 0 SECTION LOCAL DEFAULT 1
2: 000000000040021c 0 SECTION LOCAL DEFAULT 2
3: 000000000040023c 0 SECTION LOCAL DEFAULT 3
4: 0000000000400260 0 SECTION LOCAL DEFAULT 4
5: 0000000000400288 0 SECTION LOCAL DEFAULT 5
6: 00000000004003c0 0 SECTION LOCAL DEFAULT 6
7: 0000000000400502 0 SECTION LOCAL DEFAULT 7
8: 0000000000400520 0 SECTION LOCAL DEFAULT 8
9: 0000000000400560 0 SECTION LOCAL DEFAULT 9
10: 0000000000400590 0 SECTION LOCAL DEFAULT 10
11: 0000000000400638 0 SECTION LOCAL DEFAULT 11
12: 0000000000400660 0 SECTION LOCAL DEFAULT 12
13: 00000000004006e0 0 SECTION LOCAL DEFAULT 13
14: 00000000004006f0 0 SECTION LOCAL DEFAULT 14
15: 0000000000400944 0 SECTION LOCAL DEFAULT 15
16: 0000000000400950 0 SECTION LOCAL DEFAULT 16
17: 0000000000400958 0 SECTION LOCAL DEFAULT 17
18: 00000000004009b0 0 SECTION LOCAL DEFAULT 18
19: 0000000000600b30 0 SECTION LOCAL DEFAULT 19
20: 0000000000600b40 0 SECTION LOCAL DEFAULT 20
21: 0000000000600b48 0 SECTION LOCAL DEFAULT 21
22: 0000000000600b50 0 SECTION LOCAL DEFAULT 22
23: 0000000000600d50 0 SECTION LOCAL DEFAULT 23
24: 0000000000600d58 0 SECTION LOCAL DEFAULT 24
25: 0000000000600da8 0 SECTION LOCAL DEFAULT 25
26: 0000000000600dc0 0 SECTION LOCAL DEFAULT 26
27: 0000000000000000 0 SECTION LOCAL DEFAULT 27
28: 0000000000000000 0 SECTION LOCAL DEFAULT 28
29: 0000000000000000 0 SECTION LOCAL DEFAULT 29
30: 0000000000000000 0 SECTION LOCAL DEFAULT 30
31: 0000000000000000 0 SECTION LOCAL DEFAULT 31
32: 0000000000000000 0 SECTION LOCAL DEFAULT 32
33: 0000000000000000 0 SECTION LOCAL DEFAULT 33
34: 0000000000000000 0 FILE LOCAL DEFAULT ABS init.c
35: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
36: 0000000000600b48 0 OBJECT LOCAL DEFAULT 21 __JCR_LIST__
37: 0000000000400720 0 FUNC LOCAL DEFAULT 14 deregister_tm_clones
38: 0000000000400760 0 FUNC LOCAL DEFAULT 14 register_tm_clones
39: 00000000004007a0 0 FUNC LOCAL DEFAULT 14 __do_global_dtors_aux
40: 0000000000600ed0 1 OBJECT LOCAL DEFAULT 26 completed.6938
41: 0000000000600b40 0 OBJECT LOCAL DEFAULT 20 __do_global_dtors_aux_fini_array_entry
42: 00000000004007c0 0 FUNC LOCAL DEFAULT 14 frame_dummy
43: 0000000000600b30 0 OBJECT LOCAL DEFAULT 19 __frame_dummy_init_array_entry
44: 0000000000000000 0 FILE LOCAL DEFAULT ABS class.cpp
45: 0000000000400954 1 OBJECT LOCAL DEFAULT 16 std::piecewise_construct
46: 0000000000600ed8 1 OBJECT LOCAL DEFAULT 26 std::__ioinit
47: 0000000000400835 62 FUNC LOCAL DEFAULT 14 __static_initialization_and_destruction_0(int, int)
48: 0000000000400873 21 FUNC LOCAL DEFAULT 14 _GLOBAL__sub_I_second
49: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
50: 0000000000400b28 0 OBJECT LOCAL DEFAULT 18 __FRAME_END__
51: 0000000000600b48 0 OBJECT LOCAL DEFAULT 21 __JCR_END__
52: 0000000000000000 0 FILE LOCAL DEFAULT ABS
53: 0000000000400958 0 NOTYPE LOCAL DEFAULT 17 __GNU_EH_FRAME_HDR
54: 0000000000600d58 0 OBJECT LOCAL DEFAULT 24 _GLOBAL_OFFSET_TABLE_
55: 0000000000600b40 0 NOTYPE LOCAL DEFAULT 19 __init_array_end
56: 0000000000600b30 0 NOTYPE LOCAL DEFAULT 19 __init_array_start
57: 0000000000600b50 0 OBJECT LOCAL DEFAULT 22 _DYNAMIC
58: 0000000000600da8 0 NOTYPE WEAK DEFAULT 25 data_start
59: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::basic_ostream<char, std::char_traits<char> >::operator<<(int)@@GLIBCXX_3.4
60: 0000000000400940 2 FUNC GLOBAL DEFAULT 14 __libc_csu_fini
61: 0000000000600ed4 4 OBJECT GLOBAL DEFAULT 26 second
62: 00000000004006f0 42 FUNC GLOBAL DEFAULT 14 _start
63: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
64: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
65: 0000000000400944 0 FUNC GLOBAL DEFAULT 15 _fini
66: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::ios_base::Init::Init()@@GLIBCXX_3.4
67: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_2.2.5
68: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit@@GLIBC_2.2.5
69: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char)@@GLIBCXX_3.4
70: 00000000004006c0 0 FUNC GLOBAL DEFAULT UND std::ios_base::Init::~Init()@@GLIBCXX_3.4
71: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable
72: 0000000000400950 4 OBJECT GLOBAL DEFAULT 16 _IO_stdin_used
73: 0000000000400888 23 FUNC WEAK DEFAULT 14 First::First(int)
74: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
75: 0000000000600da8 0 NOTYPE GLOBAL DEFAULT 25 __data_start
76: 00000000004008a0 46 FUNC WEAK DEFAULT 14 First::printStuff()
77: 0000000000400888 23 FUNC WEAK DEFAULT 14 First::First(int)
78: 0000000000600db8 0 OBJECT GLOBAL HIDDEN 25 __TMC_END__
79: 0000000000600dc0 272 OBJECT GLOBAL DEFAULT 26 std::cout@@GLIBCXX_3.4
80: 0000000000600db0 0 OBJECT GLOBAL HIDDEN 25 __dso_handle
81: 00000000004008d0 101 FUNC GLOBAL DEFAULT 14 __libc_csu_init
82: 0000000000600db8 0 NOTYPE GLOBAL DEFAULT 26 __bss_start
83: 0000000000600ee0 0 NOTYPE GLOBAL DEFAULT 26 _end
84: 0000000000600db8 0 NOTYPE GLOBAL DEFAULT 25 _edata
85: 0000000000000000 0 FUNC GLOBAL DEFAULT UND operator new(unsigned long)@@GLIBCXX_3.4
86: 00000000004007e6 79 FUNC GLOBAL DEFAULT 14 main
87: 0000000000400638 0 FUNC GLOBAL DEFAULT 11 _init
我的问题是,变量first
在哪里?我在转储中没有看到这个对象!请注意,second
作为符号 61 存在。我预计 first
会被破坏,但不会完全消失...
有人吗?
您的对象 first
只是一个仅存在于堆栈中的本地对象。此类对象不存储在可执行文件的数据部分中。变量 second
不同,因为它是全局的。它与它的初始值一起存储(在你的情况下是默认值,因为你没有显式实例化它)并被定义为一个符号。
example.cpp:
class Clazz {
int x; // will live wherever the instance of Clazz is created
public:
Clazz(const std::initializer_list<int> & data) {}
Clazz() : x(13) {} // "13" is either in constructor code, or .rodata
};
// these will end in .data section
// except the list parameter {1, 2, 3}, which is const and lands in .rodata
static int localInt; // local symbol, will be in .o file only in debug info
int globalInt; // global symbol
// btw, both are initialized to 0, as they are defined in .data
static Clazz *classPtr = nullptr;
Clazz classInstance( {1, 2, 3} );
// all global symbols from .data/.rodata/.bss/.text (.code) sections
// will be visible in symbol table of executable (including the "foo" below)
// everything else defined below (except foo) is runtime allocated,
// and can't have any fixed address in symbol table, so it will not show there.
void foo(int param) { // param is either on stack or in register (ABI specific)
Clazz localVar; // localVar instance is living on the stack space
classPtr = new Clazz({});
// Instance of Clazz pointed at by classPtr lives in global heap memory
// If not released by explicit "delete classPtr;" during runtime,
// it will cause memory leak (avoid using naked pointers like this).
int localInt; // localInt lives on stack too, uninitialized = undefined value!
// On the contrary to *classPtr the localVar is released upon exiting it's scope
}
堆栈或堆实例都不在 ELF 文件中,在 ELF 文件中只有能够操作实例和创建实例的代码(在堆栈或堆上,通过将其实例化为 global/local变量,或 new
).
因此,除非您将某些类型实例化到 .data/.bss 部分(即在函数之外将其定义为该 .cpp 文件的 global/local),否则您无法确定变量将通过查看 executable.
的符号 table 来保存在这段代码中,您只打印参数的数量,argc 是包含命令的参数数量,argv 是字符串数组,它是由 space[=10= 分隔的命令后的单词]
我认为,为了理解 readelf 的输出,我们首先需要了解一点编译器的工作原理。
基本上,编译器将 C/C++ 文件作为输出并生成一个 executable 文件,每个 C/C++ 通常由函数和变量构建。 为了进一步理解这一点,我们还需要讨论称为 "scopes" 的东西,范围基本上是代码中识别的位置 - 在我们的代码中,我们定义的对象/函数是可识别和可访问的。
例如让我们使用这段代码
#include <stdio.h>
int myGlob = 5;
int foo()
{
int a = 5;
printf("Hey this is foo -> %d\n",a + 1);
return a + 1;
}
int goo()
{
int b = 5;
printf("Hey this is goo -> %d\n",b - 1);
return b - 1;
}
int main()
{
printf("glob(%d) foo(%d) goo(%d)",myGlob,foo() - 1, goo() +1 );
return 0;
}
我们有三个函数和一个全局变量
foo
-> 其中有局部变量a
goo
-> 其中有局部变量b
- main -> 其中没有局部变量
- 我们还有
myGlob
这是一个全局变量
变量a
只能在foo
中访问,变量b
只能在goo
函数中访问,myGlob
只能在foo
函数中访问所有函数,但只有一个,所以 a
的范围是 foo
,b
的范围是 goo
,myGlob
的范围是整个模型,非常基本正确的?这是我们将在解释中更深入的地方。
这些函数/GLOBAL 对象中的每一个都称为符号,在编写实际代码时,您有许多模型和许多头文件相互调用和包含。编译器一次编译一个文件并为每个编译模型输出一个相应的目标文件,为了让模型识别其他模型,在每个模型上我们都包含一个叫做符号 table 的东西,它基本上是所有的集合您代码中的函数和全局变量应该可以被其他模型访问。
例如:
- 我们有
model.h
定义函数foo
- 我们有
model.c
实现了foo
- 我们有
othermodel.c
,其中包括model.h
定义和实现 调用goo
的函数 foo
现在,如果我们真的创建这样的东西,运行 阅读它,我们会看到 model.h
+ model .c
将合并为 model.o
和 othermodel.c
将生成 othermodel.o
,model.o
将在其中包含符号 foo
并且 foo
(实际代码和说明)和 othermodel.o
的实现将具有符号 goo
和 foo
但只有实现
foo
这是链接器介入的地方,当链接器需要将所有目标文件组合成一个 executable 时,它会读取哪个目标文件需要其中的哪些符号,并最终将所有文件组合成一个 executable ,我再次提醒你,符号也可能是函数和全局变量。
现在我们对符号是什么以及为什么在组合多个模型范围时使用每个符号有了更多的了解,我们可以理解为什么局部变量不应该有自己的符号
让我们回到之前的例子,在 model.o
的函数 foo
中
有一些局部变量 b
正如我们之前所说 b 只能由 foo 访问,为什么 model.o
的目标文件需要为 b
生成一个符号?除了 foo
中的代码,没有其他人可以访问该变量,那么为什么需要识别甚至知道它的存在?
现在老实说,这是对实际发生的事情的滥用,在现实生活中,局部变量保存在堆栈中,在您的指令代码中,当输入某些函数时,您的内存堆栈被手动操作以创建一些内存缓冲区保存与函数执行有关的所有局部变量和数据...所谓的缓冲区称为堆栈框架,其优点是一旦退出函数,堆栈就会被清理,并且函数会重新使用该内存和 运行 堆栈内存及其局部变量和函数元数据(例如 return 地址)与局部变量不同,全局变量如我示例中的 myGlob
或 second
在你的中保存在一个全局内存部分,所有适当的功能都可以访问它(实际上并不总是正确的,但现在让我们保持简单),并且内存的生命周期贯穿整个程序,它不会不断被重写就像堆栈内存一样,每个人都可以访问它,因此局部变量不需要符号或整个程序的生命周期。
如果你不知道,classC++/C 中的 es / structs 只是一堆不同类型的变量,在内存中按顺序排列,如果你的 class 实例是本地的,它是只是一堆局部变量一个接一个地位于堆栈内存中,编译器允许您使用一些 comfortable 名称访问这些变量,这些名称最终将被转换为偏移量,因此正如我们在前面的长文中所展示的很长的解释,你根本不应该\不会有局部变量的符号..如果你想看到你好你可以做的事情
static int hello;
这可能不会为您提供全局范围的可访问性,但却为您的变量提供了整个程序的生命周期..
无论如何希望我已经让你明白了一些事情,对不起我糟糕的英语水平:)
编辑:
顺便说一句,这绝对与您的 CPU 体系结构无关,即使您为 C++ PowerPC、MIPS 或 ARM 编译代码,它也将保持不变,唯一不同的是是实际的指令,也许是函数的地址,但这更多的是一个概念,而不是与 CPU 架构
相关