该篇博客是自己学习的总结,如果有哪里理解的不对的地方,希望大家可以指点。

一、C内存空间分布图

二、各内存区域详解

1.代码区(.text): 该区域主要存放二进制可执行文件。

2.数据区(.data): 数据区可详细分为三块区域,分别是只读数据区、初始化数据区、未初始化数据区。

1). 只读数据区(.ordata) : 顾名思义,这个区域存放的是一些常量,包括字符串常量、const修饰的全局变量;

注意一: 字符串常量都是存储在只读数据区的。看下面一个例子,

 #include <stdio.h>

 int main(void)
{
char str[] = "I Love CHINA"; printf("the address of array: %p\n", str);
printg("the address of string: %p\n", "I Love CHINA"); str[] = 'W';
printf("%s\n", str); return ;
}

调试结构为:

the address of array: 0xbfa5052f
the address of string: 0x80485f5
W Love CHINA

看到这里可能就迷糊了,上面不是说字符串常量都存放在只读数据区吗?其实原因是这样的,当我们用字符串初始化字符数组时,是先将字符串字面量存储在只读数据区,当调用该初始化所在函数时,会将在数据区的数据拷贝一份到当前数组,当前运行的程序中就有两个''I Love CHINA'';我们改变了的其实是赋值到字符数组str所对应的在栈中的空间的值,而存放在数据区的字符串常量并没有改变。

注意二: 而const修饰的局部变量还是像普通的局部变量一样存放在栈中,只是不能显式的改变该变量。

2). 初始化数据区(.rwdata): 该区域用来存放初始化不为0的全局变量和static修饰的局部变量。

3). 未初始化数据区(.bss): 与初始化数据区类似,但是它存放的是初始化为0、未初始化的全局变量和static修饰的局部变量。这样做的目的主要是为了减少可执行二进制文件占用的存储空间,特别是在一些嵌入式设备中显得尤其重要。如下图,

 #include <stdio.h>

 int arr[] = {};

 int main(void)
{
printf("hello world\n"); return ;
}

 #include <stdio.h>

 int arr[] = {};

 int main(void)
{
printf("hello world\n"); return ;
}

3. 栈: 栈存放的是程序中的局部变量,  当然函数形参、返回值也都存储在栈中。栈是由系统自动管理,变量的出栈入栈操作都由系统通过移动栈顶指针来完成来完成,并不是真正的清除变量,所以当我们使用局部变量之前一定要给它赋值,否则就是一个不确定的值。

4.堆: 堆空间解决了自动分配不灵活,对内存造成浪费等问题。可以通过malloc函数申请所需大小的空间,注意这块空间申请了之后会一直存在,所以一定要和free一起使用,等用完之后马上释放,否则会造成内存泄漏,严重会导致程序停止运行。我们使用mallco函数带来方便灵活的同时,也带来了内存碎片的问题,所以当要求程序长时间运行时,必不可免的就要解决malloc带来的内存碎片问题。

C程序运行时的内存分布的更多相关文章

  1. c++程序运行时的内存分配《转》

    C++中,内存分为5个区:堆.栈.自由存储区.全局/静态存储区和常量存储区. 1.栈:是由编译器在需要时自动分配,不需要时自动清除的变量存储区.通常存放局部变量.函数参数等. 2.堆:是由new分配的 ...

  2. 实例分析C程序运行时的内存结构

      先验知识 静态变量存储在静态存储区,局部变量存储在动态存储区(栈),代码存放在代码区 寄存器,EBP指向栈底,ESP指向栈顶,EIP指向正在执行指令的下一条指令,三个寄存器中保存的都是地址,32位 ...

  3. Qt使用windows API获取程序运行时占用内存 good

    使用的是psapi.h中的GetProcessMemoryInfo函数,但是运行到该函数时就强制退出了. 后来,百度到原因是 原来Qt编译时加了-mthread,createprocess时要使的Ha ...

  4. [Java]程序运行时的内存分配

    本文出处:<Thinking in JAVA> 寄存器这是最快的存储区,因为它位于不同于其他存储区的地方--处理器内部.但是寄存器的数量极其有限,所以寄存器根据需求进行分配.你不能直接控制 ...

  5. c++ 程序编译后运行时的内存分配

    程序编译后运行时的内存分配 太好的文章了,看到不得不转,转自:http://blog.sina.com.cn/s/blog_5420e0000101a0w1.html 一.编译时与运行时的内存情况 1 ...

  6. java程序运行时内存分配详解 (转)

    转自:http://www.tuicool.com/articles/uU77v2 一.  基本概念 每运行一个java程序会产生一个java进程,每个java进程可能包含一个或者多个线程,每一个Ja ...

  7. java程序运行时内存分配详解

    java程序运行时内存分配详解 这篇文章主要介绍了java程序运行时内存分配详解 ,需要的朋友可以参考下   一. 基本概念 每运行一个java程序会产生一个java进程,每个java进程可能包含一个 ...

  8. Java程序运行时内存划分

    1.Java程序跨平台运行的原因 主要原因是:各种平台的JVM和字节码文件 Java源程序--具体平台的机器代码文件---被编译器翻译成平台无关的Class文件,又用特定JVM运行字节码文件,JVM在 ...

  9. 关于Class对象、类加载机制、虚拟机运行时的内存布局的全面解析和推测

    简介: 本文是对Java的类加载机制,Class对象,反射原理等相关概念的理解.验证和Java虚拟机中内存布局的一些推测.本文重点讲述了如何理解Class对象以及Class对象的作用. 欢迎探讨,如有 ...

随机推荐

  1. SQLite事务、错误与自动回滚

    BEGIN TRANSACTION begin-stmt: hide commit-stmt: hide rollback-stmt: hide No changes can be made to t ...

  2. Python 浅拷贝copy()与深拷贝copy.deepcopy()

    首先我在这介绍两个新的小知识,要在下面用到.一个是函数 id() ,另一个是运算符 is.id() 函数就是返回对象的内存地址:is 是比较两个变量的对象引用是否指向同一个对象,在这里请不要和 == ...

  3. range()函数

    range()函数 函数说明: range(start, stop[, step]) -> range object,根据start与stop指定的范围以及step设定的步长,生成一个序列.参数 ...

  4. Nginx缓存服务

    Nginx缓存服务 1.缓存常见类型 2.缓存配置语法 3.缓存配置实践 4.缓存清理实践 5.部分页面不缓存 6.缓存日志记录统计 通常情况下缓存是用来减少后端压力, 将压力尽可能的往前推, 减少后 ...

  5. MSYS2 简单配置

    Windows 下用 SWIG 打包 C/C++ 为 Python 接口的时候,需要用到 32-bit/64-bit 编译器,MSYS2 给出了个一揽子方案,安装见其官方网站. 本文主要记录 MSYS ...

  6. StackExchange.Redis使用配置

    转自:http://www.cnblogs.com/deosky/p/4848403.html Configurationredis有很多不同的方法来配置连接字符串 , StackExchange.R ...

  7. [BZOJ4005][JLOI2015]骗我呢-[dp+容斥]

    Description 传送门 Solution 如果单独考虑一行i,则左边位置的数严格比右边位置的数小.而一行有m个位置,它们可以填[0,m]这m+1个数,则必然有一个数不存在. 定义第i行的第j位 ...

  8. Elasticsearch 思维导图集锦(持续更新...)

    目录 引言 思维导图 全文搜索 Elastic 基础 Query DSL Multi Match Query 系列文章列表 参考 引言 本文主要是对 elasticsearch 的一些知识点使用思维导 ...

  9. Arduino通过L9110进行电机控制

    L9110S是为控制和驱动电机设计的两通道推挽式功率放大专用集成电路器件,将分立电路集成在单片IC之中,使外围器件成本降低,整机可靠性提高. 该芯片有两个TTL/CMOS兼容电平的输入,具有良好的抗干 ...

  10. python--Numpy and Pandas 笔记01

    博客地址:http://www.cnblogs.com/yudanqu/ 1 import numpy as np import pandas as pd from pandas import Ser ...