- 浏览: 147316 次
- 性别:
- 来自: 帝都
文章分类
最新评论
-
jackchen0227:
汗,谢谢啊
joj 1817: Triangle 三角形的判定 -
RootJ:
输出时候没有写:号。。。
joj 1817: Triangle 三角形的判定 -
jackchen0227:
嗯再捡捡。。
不带括号的四则运算 -
ruby_windy:
不是大二实验课写的么...
不带括号的四则运算
C语言跟内存分配方式
(1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。
(2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
(3)从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多
C语言跟内存申请相关的函数主要有 alloca,calloc,malloc,free,realloc,sbrk等.
其中alloca(注意此处没有写错,是alloca )是向栈 申请内存,因此无需释放. malloc分配的内存是位于堆中 的,并且没有初始化内存的内容,因此基本上malloc之后,调用函数memset来初始化这部分的内存空间.
calloc则将初始化这部分的内存 ,设置为0. 而realloc则对malloc申请的内存进行大小的调整 .申请的内存最终需要通过函数free来释放. 而sbrk则是增加数据段的大小 ;
malloc/calloc/free基本上都是C 函数库实现的,跟OS无关.C函数库内部通过一定的结构来保存当前有多少可用内存.如果程序malloc的大小超出了库里所留存的空间,那么将首先调用 brk系统调用来增加可用空间,然后再分配空间.free时,释放的内存并不立即返回给os,而是保留在内部结构中. 可以打个比方: brk类似于批发,一次性的向OS申请大的内存,而malloc等函数则类似于零售,满足程序运行时的要求.这套机制类似于缓冲.
使用这套机制的原因: 系统调用不能支持任意大小的内存分配(有的系统调用只支持固定大小以及其倍数的内存申请,这样的话,对于小内存的分配会造成浪费; 系统调用申请内存代价昂贵,涉及到用户态和核心态的转换. 函数malloc()和calloc()都可以用来分配动态内存空间,但两者稍有区别。
malloc()函数有一个参数,即要分配的内存空间的大小:
Void *malloc(size_t size);
calloc()函数有两个参数,分别为元素的数目和每个元素的大小,这两个参数的乘积就是要分配的内存空间的大小:
void*calloc(size_t numElements,size_t sizeOfElement);
原型 :extern void *realloc(void *mem_address, unsigned int newsize);
如果调用成功,函数malloc()和calloc()都将返回所分配的内存空间的首地址。
malloc()
函数和calloc()函数的主要区别是前者不能初始化所分配的内存空间,而后者能。如果由malloc()函数分配的内存空间原来没有被使用过,则其中
的每一位可能都是0;反之,如果这部分内存空间曾经被分配、释放和重新分配,则其中可能遗留各种各样的数据。也就是说,使用malloc()函数的程序开
始时(内存空间还没有被重新分配)能正常运行,但经过一段时间后(内存空间已被重新分配)可能会出现问题。
calloc() 函数会将所分配的内存空间中的每一位都初始化为零,也就是说,如果你是为字符类型或整数类型的元素分配内存,那么这些元素将保证会被初始化为零;如果你是 为指针类型的元素分配内存,那么这些元素通常(但无法保证)会被初始化为空指针;如果你是为实数类型的元素分配内存,那么这些元素可能(只在某些计算机 中)会被初始化为浮点型的零。
malloc() 函数和calloc()函数的另一点区别是calloc()函数会返回一个由某种对象组成的数组,但malloc()函数只返回一个对象。为了明确是为一 个数组分配内存空间,有些程序员会选用calloc()函数。但是,除了是否初始化所分配的内存空间这一点之外,绝大多数程序员认 为以下两种函数调用方式没有区别:
calloc(numElements ,sizeOfElement);
malloc(numElements *sizeOfElement) ;
需要解释的一点是,理论上(按照ANSIC标准)指 针的算术运算只能在一个指定的数组中进行,但是在实践中,即使C编译程序或翻译器遵循这种规定,许多C 程序还是冲破了这种限制。因此,尽管malloc()函数并不能返回一个数组,它所分配的内存空间仍然能供一个数组使用(对realloc()函数来说同 样如此,尽管它也不能返回一个数组)。
总之,当你在calloc()函数和malloc()函数之间作选择时,你只需考虑是否要初始化所分配的内存空间,而不用考虑函数是否能返回一个数组。
当程序运行过程中malloc了,但是没有free 的话,会造成内存泄漏.一部分的内存没有被使用,但是由于没有free,因此系统认为这部分内存还在使用,造成不断的向系统申请内存,是的系统可用内存不 断减少.但是,内存泄漏仅仅指程序在运行时,程序退出时,OS将回收所有的资源.因此,适当的重起一下程序,有时候还是有点作用.
*/
在C++中,内存分成5个区,他们分别是堆、栈、自由存储区
、全局/静态存储区和常量存储区
。???
栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储区。里面的变量通常是局部变量、函数参数等。
堆,就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。
自由存储区,就是那些由malloc等分配的内存块,他和堆是十分相似的,不过它是用free来结束自己的生命的。
全局/静态存储区,全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。
常量存储区,这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改(当然,你要通过非正当手段也可以修改,而且方法很多,在《const的思考》一文中,我给出了6种方法)
明确区分堆与栈
在bbs上,堆与栈的区分问题,似乎是一个永恒的话题,由此可见,初学者对此往往是混淆不清的,所以我决定拿他第一个开刀。
首先,我们举一个例子:
void f() { int* p=new int[5]; }
这条短短的一句话就包含了堆与栈,看到new,我们首先就应该想到,我们分配了一块堆内存,那么指针p呢?他分配的是一块栈内存,所以这句话的意思就
是:在栈内存中存放了一个指向一块堆内存的指针p。在程序会先确定在堆中分配内存的大小,然后调用operator
new分配内存,然后返回这块内存的首地址,放入栈中,他在VC6下的汇编代码如下:
00401028 push 14h
0040102A call operator new (00401060)
0040102F add esp,4
00401032 mov dword ptr [ebp-8],eax
00401035 mov eax,dword ptr [ebp-8]
00401038 mov dword ptr [ebp-4],eax
这里,我们为了简单并没有释放内存,那么该怎么去释放呢?是delete p么?澳,错了,应该是delete []p,这是为了告诉编译器:我删除的是一个数组,VC6就会根据相应的Cookie信息去进行释放内存的工作。
好了,我们回到我们的主题:堆和栈究竟有什么区别?
主要的区别由以下几点:
1、管理方式不同;
2、空间大小不同;
3、能否产生碎片不同;
4、生长方向不同;
5、分配方式不同;
6、分配效率不同;
管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memory leak。
空间大小:一般来讲在32位系统下,堆内存可以达到4G的空间,从这个角度来看堆内存几乎是没有什么限制的。但是对于栈来讲,一般都是有一定的空间大小的,例如,在VC6下面,默认的栈空间大小是1M(好像是,记不清楚了)。当然,我们可以修改:
打开工程,依次操作菜单如下:Project->Setting->Link,在Category 中选中Output,然后在Reserve中设定堆栈的最大值和commit。
注意:reserve最小值为4Byte;commit是保留在虚拟内存的页文件里面,它设置的较大会使栈开辟较大的值,可能增加内存的开销和启动时间。
碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问
题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出,在他弹出之前,在他上面的后进的栈内容已经被弹出,详
细的可以参考数据结构,这里我们就不再一一讨论了。
生长方向:对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。
分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。
分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率
比较高。堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在
堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会
分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。
从这里我们可以看到,堆和栈相比,由于大量new/delete的
使用,容易造成大量的内存碎片;由于没有专门的系统支持,效率很低;由于可能引发用户态和核心态的切换,内存的申请,代价变得更加昂贵。所以栈在程序中是
应用最广泛的,就算是函数的调用也利用栈去完成,函数调用过程中的参数,返回地址,EBP和局部变量都采用栈的方式存放。所以,我们推荐大家尽量用栈,而
不是用堆。
虽然栈有如此众多的好处,但是由于和堆相比不是那么灵活,有时候分配大量的内存空间,还是用堆好一些。
无论是堆还是栈,都要防止越界现象的发生(除非你是故意使其越界),因为越界的结果要么是程序崩溃,要么是摧毁程序的堆、栈结构,产生以想不到的结果,
就算是在你的程序运行过程中,没有发生上面的问题,你还是要小心,说不定什么时候就崩掉,那时候debug可是相当困难的:)
发表评论
-
-在二元树中找出和为某一值的所有路径--捡捡递归的使用
2012-03-30 21:05 934/* 算法要求:打印从root到叶节点的路径上的权值和 为 ... -
不带括号的四则运算
2011-10-09 21:24 1483/* 不带括号的表达式的四则运算 使用两个堆栈,一个o ... -
[zz]catalan数的分析与应用
2011-06-25 22:09 1380性质 令h(0)=1,h( ... -
joj 1085: I Think I Need a Houseboat 半圆形侵蚀
2011-06-24 20:54 9831085: I Think I Need a Ho ... -
joj 1032 deck 重心的计算
2011-06-24 19:12 11381032: Deck Result TIME ... -
joj 1186 Box of Bricks 水题
2011-06-19 09:46 9641186: Box of Bricks Re ... -
***joj 1026 the staircase 利用递归、动态规划和一道类似题目
2011-06-18 19:27 1308转自网易何国涛的博客http://zhedahht.bl ... -
joj 1062 Computer Versus Mankind 非递归最大公约数 最小公倍数
2011-06-18 15:15 12511062: Computer Versus Mankin ... -
基本的排序:非递归的堆排序
2011-06-17 15:38 0void restore(int root,int le ... -
joj 1817: Triangle 三角形的判定
2011-06-15 20:34 13491817: Triangle Result ... -
×joj 1175 The Binomial Function 递归,递归优化,非递归
2011-06-15 19:32 8781175: The Binomial Functio ... -
joj 1146 标准输入+字符串反转
2011-06-15 18:02 11761146: Word Reversal Re ... -
joj 1149Binary Number 二进制移位操作
2011-06-15 09:50 9691149: Binary Numbers R ... -
joj 2484
2011-06-14 13:35 8642484: Chinese Character A ... -
**joj:1017 fire net 递归回溯的使用
2011-06-14 12:35 11221017: Fire Net Res ... -
joj 1014 the matrix 从八个方向遍历访问矩阵
2011-06-10 20:51 12131014: The Matrix Re ... -
joj 1013 Polynomial Multiplication多项式乘法的计算
2011-06-10 19:54 13301013: Polynomial Multiplic ... -
new 与malloc的区别
2011-06-08 21:24 2491学过C++和C语言的一般都会对编程语言中的内存分配有点小困 ... -
joj 2749 大数比较大小与减法
2011-06-08 16:32 1945/* 题目不难,一个大 ... -
**joj 1903 tug of war 使用动态规划
2011-06-07 10:36 15041903: Tug of War R ...
相关推荐
5. **动态内存管理**:在游戏过程中,随着蛇的增长,需要动态地分配和释放内存空间,以存储蛇的身体信息。 #### 五、项目实现步骤 1. **初始化游戏窗口**:设置游戏窗口的大小、背景颜色等基本属性。 2. **定义蛇...
cstring,作为Microsoft MFC库中的重要成员,是C++对标准C字符串的封装,旨在解决C语言中字符串处理带来的诸多问题,如缓冲溢出和内存泄漏。这篇文章将深入探讨CString的工作原理,帮助开发者更好地理解和使用这一...
【标题】"zz.rar_hungarian algorithm_匈牙利_匈牙利算法"涉及的核心知识点是匈牙利算法,这是一门在图论中的优化算法,主要用于解决匹配问题,特别是指二分图的最大匹配问题。在计算机科学和运筹学中,匈牙利算法...
3. MIB:MIB是SNMP中的数据结构,它定义了网络设备上的可管理对象,并为这些对象分配唯一的OID(Object Identifier),使得网络管理软件可以识别和操作它们。 4. SNMP Trap:当网络设备遇到异常情况时,例如硬件...
### C/C++面试指导知识点详解 ...以上是C/C++面试中可能遇到的关键知识点。对于求职者来说,不仅要掌握这些基本概念,还需要具备解决实际问题的能力。通过不断地练习和实践,可以更好地应对面试中的各种挑战。
这个库文件提供了开发人员在编写和调试C++程序时所需的运行时支持,包括异常处理、内存分配和释放等功能。 **msvcr120d.dll** 同样是Visual C++运行时库的一部分,它主要负责提供C运行时库功能,如数学运算、字符串...
- **内存管理**:学习内存分配与回收机制、内存保护技术等。 - **文件系统**:了解嵌入式系统中常用的文件系统类型及其特点。 #### 3. 编程语言及开发工具 - **C/C++编程**:掌握C/C++语言的基础语法和高级特性,如...
- 使用静态内存分配;使用内存管理库;定期重启系统等。 ### 结论 通过对嵌入式系统的基础概念、编程语言、实时操作系统以及设计流程等方面的学习和理解,求职者可以更好地为即将到来的面试做好准备。同时,了解...
1. **C/C++**:由于其高效性和对底层硬件的直接访问能力,成为嵌入式开发中最常用的编程语言之一。 2. **Python**:虽然不如C/C++那样适用于低功耗设备,但在某些高性能嵌入式平台上仍得到广泛应用,特别是在机器...
- 内存管理:熟悉堆栈内存的区别、动态内存分配(malloc/free)和智能指针的使用。 - 高级特性:如模板、异常处理、命名空间等。 2. **操作系统基础知识**: - 实时操作系统(RTOS)原理及其与通用操作系统的...
根据给定的信息,我们可以深入探讨Objective-C中的一些关键概念及其面试题目解析,这些知识点对于理解和掌握Objective-C语言至关重要。 ### 1. Objective-C中的多重继承与多协议支持 #### 多重继承 Objective-C不...
4. **汇编器和链接器**:它们负责将源代码转换为可执行格式,并处理内存分配、符号解析等问题。 5. **仿真器和调试器**:内置的μVision调试器支持硬件和软件仿真,可以进行断点设置、变量观察、步进执行等功能。 ...
4. 编程语言规范:ACM竞赛通常要求使用C/C++或Java等语言。模板中可能会包含关于语言特性的介绍、标准库的使用说明、调试技巧等。 5. 时间和内存限制下的编程:由于ACM竞赛要求在严格的时间和内存限制下完成编程,...
- **减少内存占用**:合理管理内存,避免不必要的内存分配和释放操作。 - **提高代码效率**:利用编译器提供的优化选项,合理使用函数内联等技巧。 - **确保代码可靠性**:采用良好的编码习惯,进行充分的测试和验证...
4. **内存管理**:动态内存分配、释放等。 5. **多线程编程**:线程同步机制、互斥锁等。 #### 选择题与判断题 1. **操作系统原理**:进程管理、内存管理等。 2. **编译原理**:预处理、编译、链接等过程。 3. **...
- **内存管理**:理解堆栈的区别,动态内存分配函数的使用。 - **文件操作**:熟悉文件打开、关闭、读写等基本操作。 #### 2. 数据结构与算法 - **链表、队列、栈**等基本数据结构的操作。 - **排序算法**:如冒泡...
C/C++编程基础 - 指针操作 - 内存管理 - 数据结构和算法实现 #### 2. 操作系统原理 - 进程间通信(IPC) - 线程同步机制 - 内存管理和虚拟内存 #### 3. 计算机体系结构 - CPU架构(如ARM、MIPS) - 存储器层次...
此外,对于求职者来说,掌握C/C++编程语言、操作系统原理以及数据结构与算法等基础知识至关重要,这些都是华为等公司笔试中的常见考点。希望以上的总结能帮助大家更好地准备面试,成功进入心仪的公司。
2. **算法实现**:将PID算法以适当的编程语言(通常是C或C++)实现。在编程过程中,要考虑微控制器的处理能力、内存大小等因素。 3. **中断服务**:为确保PID控制的实时性,需要使用定时器中断来周期性地执行PID...