C程序的构成及动态内存分配
对一个程序,通常的理解就是,源码编译成机器代码,然后通过机器解释运行。不过是怎样编译成机器代码,和怎样运行的,无疑是个值得探讨的问题。怎样编译成机器代码,过程就是源码的编译、链接,编译器做了这些事。而怎样运行,却不是哪个器件自己一己之力就可以做到的。机器代码要在机器上运行,就得要请求硬件资源。涉及最多的就是CPU和内存了。CPU进行逻辑控制和运算,内存用于运行过程中的数据的快速交互场所。
一个C程序从其自身代码的结构上来看,编译过后不过是一段代码。而这段代码,从磁盘系统加载到内存中被称为代码段或正文段(code/text segment)的地方。在内存中的正文段是共享的。所以,当我们运行同一程序的多个进程时,在内存中,只有一个程序代码的副本。当然,为了防止有人要做坏事,正文段的权限常常都是只读的。
一个只有谋略,而手下无兵的将领,在战场上是什么也做不了的。程序代码,当然也不可能纯粹的都是逻辑描述。还必须得有逻辑作用的对象和结果——数据。也即程序中的各种变量。不同变量,在程序中的地位看起来除了作用域与生存周期外,都大同小异。不过,它们的实现确实非常的不同的。
程序中的未初始化的全局变量,存储在一个被称为未初始化数据段的地方。也即是bss(block started by symbol)段。同时,内核会自动的将此段中的数据初始化为0或空指针。如,函数外的声明:
int sum[10];
使得该变量存放在bss段中。
既然有了未初始化的全局变量,当然也就有初始化了的全局变量。它们存放在一个称为初始化数据段(常简称为数据段)的地方。拥有全局的作用域整个程序的生存周期。(Right?) 如,任函数外的声明:
int tmp = 99;
使得该变量存放在数据段中。
当然,还有一个叫堆栈段的东西。自动变量及每次函数调用是所需要保存的信息都存放在这里。堆栈的特点是先进后出(FILO)及数据存放的周期短,即进栈出栈操作很频繁。自动变量通常都是作为临时变量存在的,存在周期短,非常时候放在栈中。(Right?) 而函数调用时的的现场信息,可以利用堆栈的先进先出特点很方便的进行保护和恢复。典型的,递归的实现就是用了堆栈进行,因为堆栈是一层层向下增长的,所以在子函数中是不会覆盖调用函数的参数的。特别得要注意的一点是,主函数main中的变量,也是自动变量。因为主函数也是函数啊!
最后,作为C和C++特有的动态内存分配。是在运行时,利用堆来动态的进行内存分配的。所以动态分配的内存都具有全局的作用域(从分配后开始)。而生存周期而是直到其被释放前。动态内存的分配,其实就是向内核请求一块内存资源,而释放呢,就是将资源返还给内核。所以动态分配的内存都必须在不再需要时释放。不然可能会造成内存泄露及动态分配失败等恼人的问题。
看到这里,我们可以发现。一个C程序,其代码是被加载到了内存的代码段中,而其代码段中的一个个的变量,并没有实际的存放数据,数据根据情况的不同存放在了bbs段,数据段,堆栈段及堆中,代码段中的变量,存放的是一个指向各个实际存放地方的指针。(Right?)
典型的C内存分布图:

再说说C中动态内存管理。在C中,主要由标准头文件<stdlib.h>中定义的几个函数来进行内存管理:
void* malloc(size_t size) void* calloc(size_t nobj, size_t size) void* realloc(void *p, size_t size) void* free(void *p)
上面这四个函数,都返回一个void* 指针。在C中,void* 指针可以接收任意类型指针,同时,可以不经强制类型转换直接传递给任意类型指针。而在C++中,前一种情况一样,后一种情况必须进行强制类型转换。
先说说malloc,它接收一个size_t 类型的参数作为请求的内存的大小,以字节为单位。所以,在内存分配中,通常会用到sizeof运算符来获取要分配的数据类型的大小。如:
int *p = malloc(sizeof(int));
为一个int类型的指针 p 分配了一段内存区域。
calloc函数,用于为一个数组对象分配内存,第一个参数为数组的大小,第二个参数为每中数据类型的大小。一般calloc用得不多,可以直接用malloc替代。
realloc函数,用于调整已分配内存的大小。当你发现你的当前内存太多或太小时,就可以用realloc来进行内存的调整了。
所有这三个内存分配函数失败时都会返回NULL,所以可以通过检查返回值来判断内存分配是否成功。
最后,free函数,用于释放使用上述三个函数动态分配的内存。并且必须进行释放。
C中的内存分配函数的实现是由系统来完成的。所以不同系统会有不同的实现。UNIX-like系统中,一般是由sbrk系统调用来实现的。(更具体?)
在C++中,内存管理主要用操作符new 和 delete。相对C来说更方便一些,并且效率更高。不过,有个地方我没想明白的是,为何STL中的内存管理要单独写一个allocator来实现。还是new和delete不够强大?嗯,毕竟不了解new 和 delete的实现。
转载请注明地址: http://www.qyspaces.com/?p=262
C程序的构成及动态内存分配的更多相关文章
- SQLite剖析之动态内存分配
SQLite通过动态内存分配来获取各种对象(例如数据库连接和SQL预处理语句)所需内存.建立数据库文件的内存Cache.保存查询结果. 1.特性 SQLite内核和它的内存分配子系统提供以下特性 ...
- C和指针 第十一章 动态内存分配
声明数组时,必须指定数组长度,才可以编译,但是如果需要在运行时,指定数组的长度的话,那么就需要动态的分配内存. C函数库stdlib.h提供了两个函数,malloc和free,分别用于执行动态内存分配 ...
- 动态内存分配导致Javascript性能的问题
内存分配对性能的影响是很大的,分配内存本身需要时间,垃圾回收器回收内存也需要时间,所以应该尽量避免在堆里分配内存.不过直到最近优化HoLa cantk时,我才深刻的体会到内存分配对性能的影响,其中有一 ...
- C++动态内存分配
C++动态内存分配1.堆内存分配 :C/C++定义了4个内存区间:代码区,全局变量与静态变量区,局部变量区即栈区,动态存储区,即堆(heap)区或自由存储区(free store). 堆的概念:通常定 ...
- C动态内存分配(C与指针实例)
主要初步介绍malloc.free.calloc.realloc的基本.日后会有更详细的内容. malloc.free分别用于动态内存分配和释放. malloc会从内存池里提取一块合适的内存(连续的) ...
- C++学习笔记(十一):void*指针、类型转换和动态内存分配
void*指针 void关键字表示“空类型”的概念.但是,这里的“空类型”不表示“任意类型”,而是表示不存在的意思,也就是说C/C++不允许你写语句void a,不存在类型为void的东西. void ...
- 转: Linux C 动态内存分配 malloc及相关内容 .
一.malloc()和free()的基本概念以及基本用法: 1.函数原型及说明: void *malloc(long NumBytes):该函数分配了NumBytes个字节,并返回了指向这块内存的指针 ...
- 动态内存分配(new)和释放(delete)
在之前我们所写过的程序中,所必需的内存空间的大小都是在程序执行之前就已经确定了.但如果我们需要内存大小为一个变量,其数值只有在程序运行时 (runtime)才能确定,例如有些情况下我们需要根据用户输入 ...
- iOS开发——C篇&动态内存分配
再C语言中关于内存是一个很重要的知识点,所以今天我就从c语言的内存分配开始为大家解析一下C语言再iOS开发中非常重要的一些知识. 1:malloc函数的介绍 C语言中开辟内存空间:malloc函数 再 ...
随机推荐
- JavaScript- The Good Parts Chapter 4
Why, every fault’s condemn’d ere it be done:Mine were the very cipher of a function. . .—William Sha ...
- mac下firefox复制粘贴失效解决办法
现象:复制粘贴只能在firefox上操作,也就是其他应用内的内容无法复制到firefox,firefox的内容也无法复制其他应用,但是firefox自己的内容可以复制本身(比如各个tab页之间复制) ...
- Step2:配置Oracle Dataguard
接着step1我用Rman duplicate测试下. 1,2两步请参考step1中的1,2 3.startup nomount (standby),一定要是nomount. 4.rman dupli ...
- get和post,session和cookie的一些说明
1.GET和POST的区别 A. 从字面意思和HTTP的规范来看,GET用于获取资源信息而POST是用来更新资源信息. B. GET提交请求的数据实体会放在URL的后面,用?来分割,参数用& ...
- Unity3D问题之EnhanceScollView选择角色3D循环滚动效果实现
需求 呈现3D效果(2D素材)选择角色效果 滚动保证层级.缩放比例.间距正常尾随 循环滚动 这个界面需求一般也会有游戏会採用(貌似有挺多) 怎样实现 实现技术关键点 (3D循环效果,依据数学函数和细致 ...
- Android-怎样用命令行进行打包
转载请标明出处:http://blog.csdn.net/goldenfish1919/article/details/40978859 1.生成R文件 aapt package -f -m -J . ...
- PHP 函数:intval()
intval 变量转成整数类型. 语法: int intval(mixed var, int [base]); 返回值: 整数 函数种类: PHP 系统功能 内容说明:本函数可将变量转成整数类型. ...
- javascript网页弹出层练习
网页中经常出现很多"popup"弹窗效果,这里做一个练习,给我们初学者一个参考. HTML代码: <div id="popup"></div& ...
- cardslib
https://github.com/gabrielemariotti/cardslib
- UVA 10714 Ants 蚂蚁 贪心+模拟 水题
题意:蚂蚁在木棍上爬,速度1cm/s,给出木棍长度和每只蚂蚁的位置,问蚂蚁全部下木棍的最长时间和最短时间. 模拟一下,发现其实灰常水的贪心... 不能直接求最大和最小的= =.只要求出每只蚂蚁都走长路 ...