谈一谈c/c++程序的内存布局

2021/12/9 7:17:16

本文主要是介绍谈一谈c/c++程序的内存布局,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

文章目录

    • 内存布局
      • 文本段
      • 初始化数据段
      • 未初始化数据段 (bss)
      • 堆区
      • 栈区
    • 如何查看一个程序的内存布局

内存布局

一个C 程序的典型内存布局由以下几部分组成,

  • 文本段
  • 初始化数据段
  • 未初始化的数据段(bss)
  • 堆区
  • 栈区
    在这里插入图片描述

文本段

文本段也叫代码段,包含编译程序的机器码。通常文本段是可共享的,因此对于频繁执行的程序(例如文本编辑器、C 编译器、shell 等),只需要在内存中保留一个副本。可执行目标文件的文本段通常是只读段,以防止程序被意外修改。

初始化数据段

初始化数据段存储所有预先初始化的全局变量、静态变量、常量和外部变量(用 extern 关键字声明的变量),注意这部分存储的变量都是由程序员显式初始化过的,而不是由编译器初始化的。该段可以进一步分为只读初始化数据段和读写初始化数据段,

#include <stdio.h>
/*  global variable stored in Initialized Data Segment in read-write area*/
char c[]="rishabh tripathi";   
/* global variable stored in Initialized Data Segment in read-only area*/  
const char s[]="HackerEarth";    
int main()
{
    static int i=11;          /* static variable stored in Initialized Data Segment*/
    return 0;
}

未初始化数据段 (bss)

在程序开始执行之前,该段中的数据被初始化为算术 0。未初始化的数据从数据段的末尾开始,包含所有初始化为 0 或在源代码中没有显式初始化的全局变量和静态变量。

bss - block started by symbol

#include <stdio.h>

char c;               /* Uninitialized variable stored in bss*/

int main()
{
    static int i;     /* Uninitialized static variable stored in bss */
    return 0;
}

堆区

堆是通常发生动态内存分配的段。当需要使用 malloccalloc 函数分配更多内存时,堆会向上增长。 堆区由进程中的所有共享库和动态加载的模块共享。

malloccalloc都是c语言中的动态内存分配的函数,此外c语言中还可以使用realloc函数重新分配内存(重新分配的内存与原内存相比,可大可小)。在c++中动态分配内存不是使用函数进行的,而是使用关键字new.

#include <stdio.h>
int main()
{
 /* memory allocating in heap segment */
    char *p=(char*)malloc(sizeof(char));   
    return 0;
}

栈区

栈区用于存储所有局部变量,用于向函数传递参数以及函数调用结束后要执行的指令的返回地址(这样函数return之后,能够接着之前的指令继续进行)。局部变量具有定义它们的块的作用域,它们是在控制进入块时创建的。所有递归函数调用都添加到堆栈中。

正是因为栈区的以上特点,我们可以看出在以下情况下,会发生栈溢出

  • 局部变量太大 (这个大可能是真的有比较大的结构体变量,类对象,局部数组,或者太多的局部变量等等)
  • 函数调用深度太深,这样我们的要返回执行的指令地址就要不停的压栈
  • 同理,如果递归深度太深,也会造成压栈太多,从而栈溢出

要解决栈溢出的问题,我们的对应的方法是,将大的对象放在堆上;避免过深的调用;递归少用(如果必须要用,那一定要做深度限制)

栈和堆通常位于进程虚拟地址的两端,然后使用时不断的向中间靠拢,当两者相遇时,也就空间耗尽了。

以上80%的内容出自下边的文章,在翻译时做了部分修改,并且加入了自己的一些理解,若有兴趣可读原文。
https://www.hackerearth.com/practice/notes/memory-layout-of-c-program/

如何查看一个程序的内存布局

在windows下可以使用size命令查看程序的内存布局,

size .\VRS.exe

我们将得到以下返回值,

   text    data     bss     dec     hex filename
 615002    8704       0  623706   9845a .\VRS.exe


这篇关于谈一谈c/c++程序的内存布局的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程