C++各变量在不同数据段的分配(全局(静态)变量,Const,局部变量等)

本文深入解析了不同类型的变量在程序中的存储位置,包括static变量、全局变量、局部变量及动态分配变量,详细介绍了它们分别存储在bss段、全局数据段、栈和堆的具体情况,并通过readelf命令展示了Ubuntu64位系统下可执行文件的ELF信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

环境Ubuntu 64位系统 + g++5.4
1.static变量或全局变量生命周期为程序生命周期,存放在bss段(全局未初始化段)或者全局数据段。
2.函数内局部变量(含const变量)在栈内。
3.动态分配在堆内。

g_iUnInit 's addr=0x6022b4 value:0 //全局未初始化变量 bss段
g_iInit 's addr=0x6020a0 value:100 //全局已初始化变量 全局数据段
stiUnInit 's addr=0x6022bc value:0 //静态(函数体外)为初始化变量 bss段
stiInit 's addr=0x6020a4 value:10 // 静态已初始化变量 全局数据段
ciInit 's addr=0x401404 value:11 //全局const变量(const实际只在当前文件可见) rodata段 只读数据段
l_stiUnInit 's addr=0x6022c0 value:0 //main函数内 静态未初始化变量 bss段
l_stiInit 's addr=0x6020a8 value:2 // main函数内 静态已初始化变量 全局数据段
l_iUnInit 's addr=0x7ffd7f2b285c value:0 //main函数内 未初始化变量 栈内
l_iInit 's addr=0x7ffd7f2b2860 value:3//main函数内 已初始化变量 栈内
l_ci 's addr=0x7ffd7f2b2864 value:4 //main函数内 已初始化const变量 栈内
new char addr:0x87e030 //main函数内 new分配变量 堆内
malloc int addr:0x87e050//main函数内 malloc分配变量 堆内

readelf -S known 查看可执行文件elf信息:
There are 31 section headers, starting at offset 0x2ed0:

Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .interp PROGBITS 0000000000400238 00000238
000000000000001c 0000000000000000 A 0 0 1
[ 2] .note.ABI-tag NOTE 0000000000400254 00000254
0000000000000020 0000000000000000 A 0 0 4
[ 3] .note.gnu.build-i NOTE 0000000000400274 00000274
0000000000000024 0000000000000000 A 0 0 4
[ 4] .gnu.hash GNU_HASH 0000000000400298 00000298
0000000000000030 0000000000000000 A 5 0 8
[ 5] .dynsym DYNSYM 00000000004002c8 000002c8
00000000000001e0 0000000000000018 A 6 1 8
[ 6] .dynstr STRTAB 00000000004004a8 000004a8
00000000000001b2 0000000000000000 A 0 0 1
[ 7] .gnu.version VERSYM 000000000040065a 0000065a
0000000000000028 0000000000000002 A 5 0 2
[ 8] .gnu.version_r VERNEED 0000000000400688 00000688
0000000000000050 0000000000000000 A 6 2 8
[ 9] .rela.dyn RELA 00000000004006d8 000006d8
0000000000000030 0000000000000018 A 5 0 8
[10] .rela.plt RELA 0000000000400708 00000708
0000000000000150 0000000000000018 AI 5 24 8
[11] .init PROGBITS 0000000000400858 00000858
000000000000001a 0000000000000000 AX 0 0 4
[12] .plt PROGBITS 0000000000400880 00000880
00000000000000f0 0000000000000010 AX 0 0 16
[13] .plt.got PROGBITS 0000000000400970 00000970
0000000000000008 0000000000000000 AX 0 0 8
[14] .text PROGBITS 0000000000400980 00000980 代码段 size:5d2
00000000000005d2 0000000000000000 AX 0 0 16
起始地址:0000000000400980
[15] .fini PROGBITS 0000000000400f54 00000f54
0000000000000009 0000000000000000 AX 0 0 4
[16] .rodata PROGBITS 0000000000400f60 00000f60 只读数据段 size 0x92
0000000000000092 0000000000000000 A 0 0 4
起始地址:0000000000400f60
[17] .eh_frame_hdr PROGBITS 0000000000400ff4 00000ff4
0000000000000044 0000000000000000 A 0 0 4
[18] .eh_frame PROGBITS 0000000000401038 00001038
000000000000013c 0000000000000000 A 0 0 8
[19] .init_array INIT_ARRAY 0000000000601df8 00001df8
0000000000000010 0000000000000000 WA 0 0 8
[20] .fini_array FINI_ARRAY 0000000000601e08 00001e08
0000000000000008 0000000000000000 WA 0 0 8
[21] .jcr PROGBITS 0000000000601e10 00001e10
0000000000000008 0000000000000000 WA 0 0 8
[22] .dynamic DYNAMIC 0000000000601e18 00001e18
00000000000001e0 0000000000000010 WA 6 0 8
[23] .got PROGBITS 0000000000601ff8 00001ff8
0000000000000008 0000000000000008 WA 0 0 8
[24] .got.plt PROGBITS 0000000000602000 00002000
0000000000000088 0000000000000008 WA 0 0 8
[25] .data PROGBITS 0000000000602088 00002088 全局数据段 size 1c
000000000000001c 0000000000000000 WA 0 0 8
地址:0000000000602088
[26] .bss NOBITS 00000000006020c0 000020a4 BSS段: size 0x128
0000000000000128 0000000000000000 WA 0 0 32
地址:00000000006020c0
[27] .comment PROGBITS 0000000000000000 000020a4
0000000000000035 0000000000000001 MS 0 0 1
[28] .shstrtab STRTAB 0000000000000000 00002dc3
000000000000010c 0000000000000000 0 0 1
[29] .symtab SYMTAB 0000000000000000 000020e0
0000000000000870 0000000000000018 30 55 8
[30] .strtab STRTAB 0000000000000000 00002950
0000000000000473 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)

<think>首先,用户的问题是关于C++不同种类变量的存储位置,包括全局变量局部变量、类变量和命名空间变量。我需要基于提供的引用和系统指令来构建回答。 关键引用: - 引用[1]:讨论了静态局部变量,说明它们存储在静态存储区,生命周期是整个程序。 - 引用[2]:涉及命名空间变量,指出命名空间不影响生命周期,只影响作用域;全局变量还是全局变量。 - 引用[3]:提到Java中的静态变量(类变量),存储在静态存储区。 - 引用[4]:讨论了C++的内存分布,包括static const整型。 - 引用[5]:给出了结构体内存对齐的例子,但主要针对内存布局,不是变量存储位置。 我需要将这些信息整合成一个清晰的回答。回答结构应该: 1. 使用中文。 2. 对于行内数学表达式,使用$...$格式(但在这个问题中可能不涉及数学表达式)。 3. 独立公式使用$$...$$格式(如果适用)。 4. 在回答末尾自然地添加引用标识。 5. 生成相关问题。 回答内容: - **全局变量**:存储在全局/静态存储区(data或bss)。生命周期是整个程序。 - **局部变量**:存储在栈上。生命周期是函数调用期间。 - **类变量**:如果是指类的静态成员变量,存储在静态存储区;如果是非静态成员变量,则存储在对象实例的内存中(堆或栈)。 - **命名空间变量**:本质上类似于全局变量,存储在全局/静态存储区。命名空间只影响作用域,不影响存储位置。 基于引用: - 引用[1]:静态局部变量静态存储区。 - 引用[2]:命名空间变量全局变量存储在全局域。 - 引用[3]:静态变量静态存储区。 - 引用[4]:提到了内存分布,但没有具体位置。 - 引用[5]:关于内存对齐,间接相关。 完整的内存分布: - C++程序内存分为:代码(text)全局/静态存储区(data/bss)、堆(heap)、栈(stack)。 - 全局变量静态变量(包括类的静态成员)存储在全局/静态存储区。 - 局部变量存储在栈上。 - 类成员变量(非静态)存储在对象实例的位置(堆或栈)。 - 命名空间变量:如果定义在命名空间中的全局变量,存储位置与全局变量相同。 回答结构: 1. 介绍C++内存分布概述。 2. 详细解释每种变量的存储位置。 3. 使用示例或代码片(如果需要)。 4. 总结。 5. 生成相关问题。 确保回答真实可靠:基于标准C++知识。 最后,生成相关问题。</think>### C++不同种类变量的存储位置与内存分布 在C++中,变量的存储位置取决于其作用域、生命周期和声明方式。程序内存通常分为以下几个区域:代码(text)、全局/静态存储区(data/bss)、堆(heap)和栈(stack)。下面我将逐步解释全局变量局部变量、类变量(包括静态成员变量)和命名空间变量的存储位置,并基于引用提供真实可靠的说明。 #### 1. **全局变量** - **存储位置**:全局变量存储在全局/静态存储区(data或bss)。data用于初始化的全局变量,bss用于未初始化的全局变量。 - **生命周期**:整个程序运行期间(从程序启动到退出)。 - **作用域**:全局作用域,可在整个文件中访问(需注意extern声明)。 - **示例说明**: ```cpp int globalVar = 10; // 存储在data int uninitGlobalVar; // 存储在bss ``` - 全局变量的内存分配在程序加载时完成,释放于程序结束时。这与引用[1]中描述的静态局部变量类似,但全局变量作用域更广[^1]。 #### 2. **局部变量** - **存储位置**:局部变量存储在栈(stack)上。栈由编译器自动管理,用于函数调用时的临时存储。 - **生命周期**:函数调用期间(进入函数时分配,退出函数时释放)。 - **作用域**:局部作用域,仅限于定义它的函数或代码块内。 - **示例说明**: ```cpp void func() { int localVar = 5; // 存储在栈上 } ``` - 局部变量在函数调用时压栈,退出时弹栈。如果使用`static`修饰(如静态局部变量),则存储在全局/静态存储区,但作用域仍为局部(引用[1]强调:静态局部变量生命周期为整个程序,但作用域限于函数内)[^1]。 #### 3. **类变量(类的成员变量)** - **非静态成员变量**: - **存储位置**:存储在对象实例的内存中。如果对象在栈上创建(如局部对象),则成员变量在栈上;如果对象在堆上创建(如`new`),则成员变量在堆上。 - **生命周期**:与对象实例相同(对象创建时分配,销毁时释放)。 - **作用域**:类作用域,通过对象访问。 - **示例说明**: ```cpp class MyClass { public: int memberVar; // 非静态成员变量 }; MyClass obj; // 如果obj是全局对象,memberVar在全局/静态存储区;如果是局部对象,在栈上。 ``` - **静态成员变量(类变量)**: - **存储位置**:存储在全局/静态存储区(data/bss),与全局变量相同。 - **生命周期**:整个程序运行期间。 - **作用域**:类作用域,通过类名访问(如`MyClass::staticVar`)。 - **示例说明**: ```cpp class MyClass { public: static int staticVar; // 声明静态成员变量 }; int MyClass::staticVar = 0; // 定义并初始化,存储在data ``` - 引用[3]指出:静态变量(类变量)存储在静态存储区,生命周期从类加载开始到程序结束[^3]。这与C++静态成员变量一致。 #### 4. **命名空间变量** - **存储位置**:命名空间变量本质上类似于全局变量,存储在全局/静态存储区(data/bss)。命名空间只影响作用域,不改变变量的存储位置或生命周期。 - **生命周期**:整个程序运行期间。 - **作用域**:命名空间作用域,需通过域操作符`::`访问(如`Namespace::var`)。 - **示例说明**: ```cpp namespace MyNamespace { int nsVar = 20; // 存储在data } int main() { MyNamespace::nsVar++; // 通过命名空间访问 } ``` - 引用[2]解释:命名空间解决名称冲突问题,但变量存储位置不变(如全局变量仍存储在全局域)[^2]。 #### 内存分布总结 C++程序内存布局可简化为: - **代码 (text)**:存储可执行代码。 - **全局/静态存储区 (data/bss)**:存储全局变量静态变量(包括静态局部变量和类的静态成员)、命名空间变量。 - **堆 (heap)**:动态分配的内存(如`new`/`malloc`)。 - **栈 (stack)**:存储局部变量、函数参数等。 这种分布确保了高效的内存管理:栈用于短期数据,堆用于动态对象,全局/静态存储区用于长期数据。引用[4]和[5]补充了内存对齐细节(如结构体填充),但变量存储位置的核心原则基于上述分类[^4][^5]。 #### 相关问题 1. 如何优化C++变量的内存使用以避免泄漏? 2. 静态局部变量全局变量在性能上有何差异? 3. C++中命名空间的使用有哪些最佳实践?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值