C语言之程序中内存的来源:栈 堆 数据段

简介:

程序在运行的时候,其内存的来源主要通过三种方法:  栈  堆  数据段,总体上来讲栈是一般用来存放小内存的局部变量,堆内存和数据段的属性很像,在使用的的时候,如果这个变量是伴随程序一直存在则使用全局变量,也就是放在数据段,如果一个变量使用完了就没用了,那么就适合用堆内存(先申请,然后释放即可),


一:栈(stack):

1:栈在使用的时候是编译器自动分配内存空间的,不需要程序员的干涉,其次栈的大小是有限的,所以当我们定义的变量需要大片的内存的时候就不适合使用栈,

2:栈存放的是普通变量,栈的在使用的时候是反复使用的,所以栈内存是脏的,在定义普通变量的时候,如果不对变量进行初始化,那么变量的值就是随机的。

3:栈是先进后出的,其内存空间是向下增长的。


二:堆(heap):

1:堆得使用时是由程序员来操作的,程序员通过malloc来向内存申请堆内存,使用完以后通过free来释放这部分内存,如果这部分内存在使用完以后没有进行内存的释放,那么这部分内存管理器就会认为这部分内存一直被占用的,体现出来的就是程序吃内存,也就是所谓的内存泄漏,如果没有释放内存,则被占用的内存只有当程序结束以后才会被释放。一般需要大片的内存时才使用堆,堆是先进先出的,其内存空间是向上增长的。

代码示例:

1
<span style= "font-family:'宋体', SimSun;font-size:20px;" >#include <stdio.h><br data-filtered= "filtered" >#include <stdlib.h><br data-filtered= "filtered" > int  main( void )<br data-filtered= "filtered" >{<br data-filtered= "filtered" > //申请内存<br data-filtered="filtered">int *p = (int *)malloc(100);<br data-filtered="filtered">if(p == NULL)  //错误检查<br data-filtered="filtered">{<br data-filtered="filtered">printf("error \n");<br data-filtered="filtered">return -1;<br data-filtered="filtered">}<br data-filtered="filtered">//内存使用S<br data-filtered="filtered">*(p+4) = 1024;<br data-filtered="filtered">*(p+3000) = 111;<br data-filtered="filtered">printf("*(p+3) = %d\n", *(p+4));<br data-filtered="filtered">printf("*(p+30000)) = %d\n", *(p+3000));<br data-filtered="filtered">printf("p = %p \n",p);<br data-filtered="filtered">printf("(p +4) = %p \n",(p +4));<br data-filtered="filtered"><br data-filtered="filtered">free(p);   //释放内存<br data-filtered="filtered"><br data-filtered="filtered">printf("*(p+3) = %d\n", *(p+4));<br data-filtered="filtered">printf("*(p+30000)) = %d\n", *(p+3000));<br data-filtered="filtered">printf("p = %p \n",p);<br data-filtered="filtered">printf("(p +4) = %p \n",(p +4));<br data-filtered="filtered"><br data-filtered="filtered">p = NULL;  //避免野指针<br data-filtered="filtered"><br data-filtered="filtered">return 0;<br data-filtered="filtered">}</span>

运行结果:

*(p+3) = 1024

*(p+30000)) = 111

p = 0x8efb008

(p +4) = 0x8efb018

*(p+3) = 1024

*(p+30000)) = 111

p = 0x8efb008

(p +4) = 0x8efb018

分析:

1:堆内存可以越界访问,但是实际中最好还是不要,因为你在使用的时候越界访问就意味着踩到别人了

2:堆内存在释放之后还可以访问,并且访问的值还是不变的,说明堆内存也是脏的,堆内存释放的时候并没有对使用过的没存进行清理。


三:数据段(.data )

1:一个程序主要有数据段(.data) 代码段  和bss段,不同的段具有不同的段属性

数据段:(又叫数据区、静态数据区、静态区)数据段存放的是程序的中显示初始化的全局变量(不包括初始化为0的全局变量),同时需要注意的是全局变量才算是程序的数据,局部变量不是程序变量,只是函数数据

代码段:代码段就是程序中的可执行部分,直观理解代码段就是函数堆叠组成的。代码段是只读的。

bss段:(又叫zero initial 段)bss段存放的是为显示初始化的全局变量已经初始化为0的全局变量(C语言中默认全局变量的初始化就是为0),所以可以理解为bss段就是初始化为0的数据段。

2:放在.data段的变量有两种:第一种是显式初始化为非0的全局变量,另一种是静态局部变量,也就是static修饰的局部变量(普通变量是分配在栈上面,静态局部变量是分布在.data段)



四:代码段中的特殊数据

1:C语言使用char *p = "linux";定义字符串的时候,字符串"linux"实际上是被分配到了代码段上面,换句话说这里的字符串"linux"实际上是一个常量字符串而不是变量字符串。

2:const修饰的类型常量,const的实现方法主要有两种,一种是编译的时候将const修饰的变量放在代码段去实现不可修改(因为代码段是只读的),另一种是由编译器来检查来确保const修饰的常量,但是这种实际上和普通常量样,也是被放在了数据段,所以如果绕过编译器就可以实现修改,具体实现方法是用指针去指向这个常量的内存空间,然后解引用去修改这个常量,gcc中就是这样实现的。




本文转自 菜鸟养成记 51CTO博客,原文链接:http://blog.51cto.com/11674570/1861671

相关文章
|
3月前
|
安全 C语言 C++
比较C++的内存分配与管理方式new/delete与C语言中的malloc/realloc/calloc/free。
在实用性方面,C++的内存管理方式提供了面向对象的特性,它是处理构造和析构、需要类型安全和异常处理的首选方案。而C语言的内存管理函数适用于简单的内存分配,例如分配原始内存块或复杂性较低的数据结构,没有构造和析构的要求。当从C迁移到C++,或在C++中使用C代码时,了解两种内存管理方式的差异非常重要。
143 26
|
3月前
|
安全 C语言
C语言中的字符、字符串及内存操作函数详细讲解
通过这些函数的正确使用,可以有效管理字符串和内存操作,它们是C语言编程中不可或缺的工具。
252 15
|
10月前
|
存储 编译器 程序员
【C语言】内存布局大揭秘 ! -《堆、栈和你从未听说过的内存角落》
在C语言中,内存布局是程序运行时非常重要的概念。内存布局直接影响程序的性能、稳定性和安全性。理解C程序的内存布局,有助于编写更高效和可靠的代码。本文将详细介绍C程序的内存布局,包括代码段、数据段、堆、栈等部分,并提供相关的示例和应用。
342 5
【C语言】内存布局大揭秘 ! -《堆、栈和你从未听说过的内存角落》
|
10月前
|
算法 Java
堆内存分配策略解密
本文深入探讨了Java虚拟机中堆内存的分配策略,包括新生代(Eden区和Survivor区)与老年代的分配机制。新生代对象优先分配在Eden区,当空间不足时执行Minor GC并将存活对象移至Survivor区;老年代则用于存放长期存活或大对象,避免频繁内存拷贝。通过动态对象年龄判定优化晋升策略,并介绍Full GC触发条件。理解这些策略有助于提高程序性能和稳定性。
|
10月前
|
存储 算法 Java
Java 内存管理与优化:掌控堆与栈,雕琢高效代码
Java内存管理与优化是提升程序性能的关键。掌握堆与栈的运作机制,学习如何有效管理内存资源,雕琢出更加高效的代码,是每个Java开发者必备的技能。
249 5
|
11月前
|
C语言
C语言编程中,错误处理至关重要,能提升程序的健壮性和可靠性
C语言编程中,错误处理至关重要,能提升程序的健壮性和可靠性。本文探讨了C语言中的错误类型(如语法错误、运行时错误)、基本处理方法(如返回值、全局变量、自定义异常处理)、常见策略(如检查返回值、设置标志位、记录错误信息)及错误处理函数(如perror、strerror)。强调了不忽略错误、保持处理一致性及避免过度处理的重要性,并通过文件操作和网络编程实例展示了错误处理的应用。
307 4
|
11月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
310 1
|
3月前
|
存储
阿里云轻量应用服务器收费标准价格表:200Mbps带宽、CPU内存及存储配置详解
阿里云香港轻量应用服务器,200Mbps带宽,免备案,支持多IP及国际线路,月租25元起,年付享8.5折优惠,适用于网站、应用等多种场景。
947 0
|
3月前
|
存储 缓存 NoSQL
内存管理基础:数据结构的存储方式
数据结构在内存中的存储方式主要包括连续存储、链式存储、索引存储和散列存储。连续存储如数组,数据元素按顺序连续存放,访问速度快但扩展性差;链式存储如链表,通过指针连接分散的节点,便于插入删除但访问效率低;索引存储通过索引表提高查找效率,常用于数据库系统;散列存储如哈希表,通过哈希函数实现快速存取,但需处理冲突。不同场景下应根据访问模式、数据规模和操作频率选择合适的存储结构,甚至结合多种方式以达到最优性能。掌握这些存储机制是构建高效程序和理解高级数据结构的基础。
280 1

热门文章

最新文章