Administrator
发布于 2025-12-29 / 11 阅读
0
0

进程地址空间(C++程序内存分布)

一、内存分布图

高地址
┌─────────────────┐
│     栈(stack)    │ ← 局部变量、函数调用等
├─────────────────┤
│       ↓          │
│     空洞/未使用    │
│       ↑          │
├─────────────────┤
│  内存映射区域      │ ← mmap的文件、共享内存等
├─────────────────┤
│      堆(heap)    │ ← malloc/new分配的内存
├─────────────────┤
│   BSS段(.bss)    │ ← 未初始化全局/静态变量
├─────────────────┤
│  数据段(.data)    │ ← 已初始化全局/静态变量
├─────────────────┤
│  代码段(.text)    │ ← 程序代码
└─────────────────┘
低地址

二、详细说明

  1. 代码段(Text segment):
    • 也称为只读段,存放程序的执行代码(机器指令)。
    • 通常是只读的,防止程序意外修改指令。
    • 也可能包含一些只读的常量数据,例如字符串常量。(为什么说可能?
  2. 数据段(Data segment):
    • 初始化数据段(Data segment):
      存放全局变量和静态变量(包括全局静态变量和局部静态变量)中已经初始化的部分。
    • 未初始化数据段(BSS segment):
      存放全局变量和静态变量中未初始化的部分。在程序开始执行之前,系统会将BSS段的数据初始化为0或空指针。两者有何区别?
  3. 堆(Heap):
    • 用于动态内存分配,例如使用malloc、new等分配的内存。
    • 堆的生长方向是从低地址向高地址增长。
    • 需要手动管理内存(在C++中,使用new分配的内存必须使用delete释放,否则会造成内存泄漏)。
  4. 栈(Stack):
    • 用于存放局部变量、函数参数、返回地址等。
    • 栈的生长方向是从高地址向低地址增长。
    • 栈由编译器自动管理,当函数调用结束时,其栈帧被自动销毁。
  5. 内存映射区域(Memory mapping segment):
    • 用于映射动态链接库、文件映射等。

三、验证

#include <iostream>
#include <fcntl.h>
#include <memory>
#include <sys/mman.h>
#include <unistd.h>
#include <iomanip> 

using namespace std;

// 全局变量 - 数据段
int global_init = 10;      // 已初始化数据段
int global_uninit;         // BSS段

int main() {
	std::cout << "main函数	地址: " << (void*)main << std::endl;

    //栈-局部变量 
    int local = 20;
  
    // 静态局部变量 - 数据段
    static int static_local = 30;

    // 静态局部变量 - 数据段
    static int static_local1;
  
    // 堆: 动态分配 
    int* heap_var = new int(40);
  
    // 代码段: 常量字符串 
    const char* str = "Hello";

	//内存映射:
	int fd = open("/home/235039/test/MmapBuf.test", O_RDWR | O_CREAT, 00777);  
	if(fd == -1)
	{
		return -1;
	}
	auto closeFD = [](int* fd) {
		if (fd && *fd >= 0) {
			close(*fd);
		}
		delete fd;
	};
	std::unique_ptr<int, decltype(closeFD)> ptr(new int(fd), closeFD);
	char *pMmapBuf = (char *) mmap(NULL, 100, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
	if(pMmapBuf == MAP_FAILED)
	{
		return -1;
	}

    cout << "栈-	  局部变量地址: " << &local << endl;
	cout << "内存映射-    映射地址:" << (void*)pMmapBuf<<endl;
    cout << "堆-          变量地址: " << heap_var << endl;
	cout << "数据段-全局未初始地址: " << &global_uninit << endl;
    cout << "数据段-静态局部未初地址: " << &static_local1 << endl;
    cout << "数据段-全局初始化地址: " << &global_init << endl;
    cout << "数据段-静态局部初始地址: " << &static_local << endl;
    cout << "代码段-常量字符串地址: " << (void*)str << endl;
  
    delete heap_var;
	munmap(pMmapBuf, 100);
    return 0;
}

验证结论:

image-Pxdx.png


评论