一个程序的运行是需要内存的,那么我们平常写的程序的内存都是怎么分配的呢

(1)首先我们要知道,内存是真实存在的,内存是一个物理器件。它时由操作系统管理的,我们平常只要使用它就行了,为了方便管理。操作系统提供了很多种机制来管理内存,每一种机制都有其特点。
(2)三种内存来源:栈(stack)、堆(heap)、数据区(data)
(3)我们获取内存的来源就是其中一种,(C语言程序中)

1.什么是栈?

1.1.栈的特点
(1)使用时自动分配,用完自动释放。

 #include<stdio.h>
main()
{
int a = ;
int b = ; }

总结:a和b都是局部变量,都是栈内存,自动分配和释放

(2)栈内存反复使用。使用完后不会清零,这就是为什么每次分配局部变量若不初始化就是随机值的原因。

 int a ;
printf("a = %d\n",a);
// a是随机值

(3)临时性:函数不能返回栈变量的指针。局部变量的地址是不能返回的。在一个函数内部分配的局部变量在函数结束时,其内存就已经不存在了。返回其地址是很危险的。

 #include<stdio.h>
int * test();
main()
{
int * w; //局部变量,栈上分配
w = test();
*w = ;
} int* test()
{
int a = ; //局部变量,栈上分配 局部变量,作用域为test函数,生命周期为test函数从执行到执行完毕
int *p = &a;
return p;
}

分析:

(1)test函数能不能返回p的值?

test函数中的a和p都是局部变量,作用域为test函数,生命周期为test函数从执行到执行完毕,当test函数执行完后,为a和p分配的栈上的内存已经释放了。也就是说,原来分配的地址已经不能在被a和p使用了。这里可以返回p的值,只是没有意义了,而是很危险的行为。
(2)能不能通过 *w = 20?

能访问,但可能会出错,原a的内存已经被释放,原来的地址已经不再属于a,这时候就会使程序崩溃。访问了不属于它的地址。
(3)数组越界问题 (栈溢出)

 main()
{
int arr[]; //局部变量,栈上分配 arr[] = ;
}

给arr数组分配了5个地址空间,访问第11个空间则会出错。

2.什么是堆?

(1)操作系统堆管理器管理。堆管理器是操作系统的一个模块
(2)大块内存,分配自如。按需分配。
(3)堆内存手动分配&释放,malloc,free
(4)堆内存也是反复使用的, 堆管理器不会去清零堆内存,下一个使用的变量才去清零。
(5)堆内存。从分配到释放一直属于同一个进程,之前或者之后都不可以再访问。

 //堆内存的使用范例

 main()
{
int*p=(int *)malloc(*sizeof(int));
}
//使用malloc()分配的内存是在堆上分配的
//这里的p仍旧是栈上分配,p是一个指针。该指针指向的内存是堆内存。(4000个字节的首四个字节)

3.数据区

(1)数据段:(也被称作数据区、静态数据区、静态区)程序运行所需要的数据存放在这,比如函数执行过程中调用的一些变量(全局变量),产生的一些数据。注意:全局变量才算是程序的数据,局部变量算是函数的数据,局部变量不是程序的数据。 局部变量属于栈管理,在栈分配。
(2)bss段
bss段:(也叫ZI段,zero initial 段,bss段的特点就是被初始化为0,bss段本质上也是数据段,bss段就是被初始化为0的数据段)

总结:(1)全局变量初始化为非0,存放在数据段。
static修饰的局部变量存放到数据段
(2)全局变量 未初始化 或 初始化为0,存放在bss段
(3)bss段是数据区的一部分

4.代码段

就是存放代码的地方,需要注意的是像char *p="aabbcc";这样的也会被分配的代码段,代码段的东西时不可以被修改的。

接下来我们看一个程序,具体分析,每一个变量存放在哪里

 #include<stdio.h>

 int test1 =     //全局变量,数据区
int test2 = //初始化为0的全局变量,数据区的bss段
int test3 //未初始化全局变量,数据区的bss段 char * display();//代码段 void main()
{ int ok1 = ; /* 局部变量
int ok2 = 0; 栈上分配
int ok3; */ int * pre; //局部变量指针,栈上分配
pre = display(); } int * display();
{
char * word = "he is goudan";
//代码段 int * re = (int*)malloc(*sizeof(int));
//re指针在栈分配
//re指针指向的是内存在堆上分配
//当display()函数执行完毕后,re指针本身地址被释放,
//re所指向的堆内存依旧存在(若未保留该指针则内存泄漏)
return re;
}

总结:

(1)程序经过编译后,分成不同的段,程序就是由好多个段组成的。数据段,代码段,bss段。
(2)全局变量才属于程序的数据,局部变量属于函数的数据。
(3)有些特殊数据会放在代码段,像字符串。

堆、栈、数据区、bss、代码段的更多相关文章

  1. PHP 堆 栈 数据段 代码段 存储的理解

    对象在PHP里面和整型.浮点型一样,也是一种数据类,都是存储不同类型数据用的, 在运行的时候都要加载到内存中去用,那么对象在内存里面是怎么体现的呢? 内存从逻辑上说大体上是分为4段,栈空间段.堆空间段 ...

  2. 内存布局:栈,堆,BSS段(静态区),代码段,数据段

    简介 我们程序运行的时候都是放在内存里的.根据静态.成员函数.代码段.对象.等等.放在不同的内存分块里.大概分为5块 1  栈 2  堆 3 BSS段-全局区-(静态区) 4 代码段 5 数据段 栈 ...

  3. java虚拟机 jvm 栈数据区

    java栈帧还是需要一些数据支持常量池的解析.正常方法的返回和异常的处理.大部分的java字节码指令需要进行常量池的访问,在栈帧数据区中保存着访问常量池的指针,方便程序访问java常量池.如下图所示: ...

  4. Java 底层机制(JVM/堆/栈/方法区/GC/类加载)

    转载:https://www.jianshu.com/p/ae97b692614e?from=timeline JVM体系结构 JVM是一种解释执行class文件的规范技术.   JVM体系结构 我翻 ...

  5. JVM堆 栈 方法区详解

    一.栈 每当启用一个线程时,JVM就为他分配一个JAVA栈,栈是以帧为单位保存当前线程的运行状态 栈是由栈帧组成,每当线程调用一个java方法时,JVM就会在该线程对应的栈中压入一个帧 只有在调用一个 ...

  6. java 堆 栈 方法区的简单分析

    Java里的堆(heap)栈(stack)和方法区(method) 基础数据类型直接在栈空间分配, 方法的形式参数,直接在栈空间分配,当方法调用完成后从栈空间回收.   引用数据类型,需要用new来创 ...

  7. linux进程的堆栈空间_代码段(指令,只读)、数据段(静态变量,全局变量)、堆栈段(局部变量)、栈【转】

    转自:http://blog.csdn.net/gongweijiao/article/details/8207333 原文参见:http://blog.163.com/xychenbaihu@yea ...

  8. vs中的强大的代码段管理

    vs中的代码段管理可以实现大段固定文本的快捷输入,方法: 首先编写.snippet文件如: <?xml version="1.0" encoding="utf-8& ...

  9. linux代码段,数据段,BSS段, 堆,栈(二)

    //main.cpp int a = 0; 全局初始化区  char *p1; 全局未初始化区 main() { int b; 栈 char s[] = "abc"; 栈 char ...

随机推荐

  1. IDEA字节码学习查看神器jclasslib bytecode viewer介绍

    转载来自:https://blog.csdn.net/w605283073/article/details/103209221 一.背景 很多人想学习Java反汇编后的字节码,但是一方面缺乏好的资料, ...

  2. Redis 入门到分布式 (七)Redis复制的原理与优化

    一.目录 Redis复制的原理与优化 什么是主从复制 全量复制和部分复制 复制的配置 故障处理 开发运维常见问题 二. 什么是主从复制 1.单机有什么问题? 单机如果机器故障,那么久无法及时提供服务: ...

  3. JavaScript (五) js的基本语法 - - - 面向对象、工程模式、内置对象、JSON

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一.编程思想 1.定义: 编程思想:把一些生活中做事的经验融入到程序中 面向过程:凡事都要亲力亲为,每件 ...

  4. Java实现 LeetCode 767 重构字符串(ASCII的转换)

    767. 重构字符串 给定一个字符串S,检查是否能重新排布其中的字母,使得两相邻的字符不同. 若可行,输出任意可行的结果.若不可行,返回空字符串. 示例 1: 输入: S = "aab&qu ...

  5. Java实现 LeetCode 117 填充每个节点的下一个右侧节点指针 II(二)

    117. 填充每个节点的下一个右侧节点指针 II 给定一个二叉树 struct Node { int val; Node *left; Node *right; Node *next; } 填充它的每 ...

  6. Java实现 蓝桥杯VIP 算法提高 企业奖金发放

    算法提高 企业奖金发放 时间限制:1.0s 内存限制:512.0MB 企业发放的奖金根据利润提成.利润低于或等于10万元时,奖金可提10%:利润高于10万元,低于20万元时,低于10万元的部分按10% ...

  7. java实现拍7游戏

    ** 拍7游戏** 许多人都曾经玩过"拍七"游戏.规则是:大家依次从1开始顺序数数,数到含有7或7的倍数的要拍手或其它规定的方式表示越过(比如:7,14,17等都不能数出),下一人 ...

  8. java实现股票的风险

    股票的风险 股票风险 股票交易上的投机行为往往十分危险.假设某股票行为十分怪异,每天不是涨停(上涨10%)就是跌停(下跌10%).假设上涨和下跌的概率均等(都是50%).再假设交易过程没有任何手续费. ...

  9. Java实现第八届蓝桥杯方格分割

    方格分割 题目描述 6x6的方格,沿着格子的边线剪开成两部分. 要求这两部分的形状完全相同. 如图:p1.png, p2.png, p3.png 就是可行的分割法. 试计算: 包括这3种分法在内,一共 ...

  10. 解Bug之路-记一次存储故障的排查过程

    解Bug之路-记一次存储故障的排查过程 高可用真是一丝细节都不得马虎.平时跑的好好的系统,在相应硬件出现故障时就会引发出潜在的Bug.偏偏这些故障在应用层的表现稀奇古怪,很难让人联想到是硬件出了问题, ...