内存的静态分配和c语言动态分配内存的区别

c与c++分别是怎样动态分配和释放内存的,有什么区别?
c语言提供内存动态分配的函数有:malloc、calloc、realloc,在使用这些函数时必须包含其头文件,分别为:&malloc.h&、&stdlib.h&、&alloc.h&
&&&&&1) malloc 函数: void *malloc(unsigned int size)
&&&&&在内存的动态分配区域中分配一个长度为size的连续空间,如果分配成功,则返回所分配内存空间的首地址,否则返回NULL,申请的内存不会进行初始化。
&&&&&2)calloc 函数: void *calloc(unsigned int num, unsigned int size)
&&&&&按照所给的数据个数和数据类型所占字节数,分配一个 num * size 连续的空间。
&&&&&calloc申请内存空间后,会自动初始化内存空间为 0,但是malloc不会进行初始化,其内存空间存储的是一些随机数据。
&&&&&3)realloc 函数: void *realloc(void *ptr, unsigned int size)
&&&&&动态分配一个长度为size的内存空间,并把内存空间的首地址赋值给ptr,把ptr内存空间调整为size。
&&&&&申请的内存空间不会进行初始化。
&& 释放的函数为free函数:&
&&&&free函数原型为:void free(void *ptr)
&&&&作用:释放由上面3种函数所申请的内存空间。
&&&&参数:ptr:指向需要释放的内存空间的首地址。
&&&在C++中,内存分成5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。
&&&申请和释放堆中分配的存储空间,分别使用new 和 delete 的两个运算符来完成:
&&&指针变量名 = new 类型名(初始化式);
&&&delete 指针名;
&&&&&int *pi = new int(0)
malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可以用于申请动态内存和释放内存。
对于非内部数据类型对象而言,光用malloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free.
看过本文的人也看了:
我要留言技术领域:
取消收藏确定要取消收藏吗?
删除图谱提示你保存在该图谱下的知识内容也会被删除,建议你先将内容移到其他图谱中。你确定要删除知识图谱及其内容吗?
删除节点提示无法删除该知识节点,因该节点下仍保存有相关知识内容!
删除节点提示你确定要删除该知识节点吗?静态分配和动态分配内存的区别
要弄懂这个问题,首先你得知道静态和动态指的是什么。个人觉得卡耐基上的解释很经典:
“The word static refers to things that happen at compile
time and link time when the program is constructed—as opposed to
load time or run time when the program is actually
started.”
“The term dynamic refers to things that take place when a
program is loaded and executed. ”&&
说白了,内存的静态分配和动态分配的区别主要是两个:
一是时间不同。静态分配发生在程序编译和连接的时候。动态分配则发生在程序调入和执行的时候。
二是空间不同。堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由函数malloc进行分配。不过栈的动态分配和堆不同,他的动态分配是由编译器进行释放,无需我们手工实现。&&&&
对于一个进程的内存空间而言,可以在逻辑上分成3个部份:代码区,静态数据区和动态数据区。动态数据区一般就是“堆栈”。“栈(stack)”和“堆(heap)”是两种不同的动态数据区,栈是一种线性结构,堆是一种链式结构。进程的每个线程都有私有的“栈”,所以每个线程虽然代码一样,但本地变量的数据都是互不干扰。一个堆栈可以通过“基地址”和“栈顶”地址来描述。全局变量和静态变量分配在静态数据区,本地变量分配在动态数据区,即堆栈中。程序通过堆栈的基地址和偏移量来访问本地变量。
一般,用static修饰的变量,全局变量位于静态数据区。函数调用过程中的参数,返回地址,EBP和局部变量都采用栈的方式存放。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。来源:&&&内存的静态分配和动态分配的区别主要是两个:&&&&&&一是时间不同。静态分配发生在程序编译和连接的时候。动态分配则发生在程序调入和执行的时候。&&&&& 二是空间不同。堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由函数malloc进行分配。不过栈的动态分配和堆不同,他的动态分配是由编译器进行释放,无需我们手工实现。&&&&& &&对于一个进程的内存空间而言,可以在逻辑上分成3个部份:代码区,静态数据区和动态数据区。& &&动态数据区一般就是“堆栈”。“栈(stack)”和“堆(heap)”是两种不同的动态数据区,栈是一种线性结构,堆是一种链式结构。进程的每个线程都有私有的“栈”,所以每个线程虽然代码一样,但本地变量的数据都是互不干扰。一个堆栈可以通过“基地址”和“栈顶”地址来描述。全局变量和静态变量分配在静态数据区,本地变量分配在动态数据区,即堆栈中。程序通过堆栈的基地址和偏移量来访问本地变量。&& &&一般,用static修饰的变量,全局变量位于静态数据区。函数调用过程中的参数,返回地址,EBP和局部变量都采用栈的方式存放。& &&所谓动态内存分配就是指在程序执行的过程中动态地分配或者回收存储空间的分配内存的方法。动态内存分配不象数组等静态内存分配方法那样需要预先分配存储空间,而是由系统根据程序的需要即时分配,且分配的大小就是程序要求的大小。& &&例如我们定义一个float型数组:& &&& &&float score[100];   & &&但是,在使用数组的时候,总有一个问题困扰着我们:数组应该有多大?在很多的情况下,你并不能确定要使用多大的数组,比如上例,你可能并不知道我们要定义的这个数组到底有多大,那么你就要把数组定义得足够大。这样,你的程序在运行时就申请了固定大小的你认为足够大的内存空间。即使你知道你想利用的空间大小,但是如果因为某种特殊原因空间利用的大小有增加或者减少,你又必须重新去修改程序,扩大数组的存储范围。这种分配固定大小的内存分配方法称之为静态内存分配。但是这种内存分配的方法存在比较严重的缺陷,特别是处理某些问题时:在大多数情况下会浪费大量的内存空间,在少数情况下,当你定义的数组不够大时,可能引起下标越界错误,甚至导致严重后果。&& &&我们用动态内存分配就可以解决上面的问题. 所谓动态内存分配就是指在程序执行的过程中动态地分配或者回收存储空间的分配内存的方法。动态内存分配不象数组等静态内存分配方法那样需要预先分配存储空间,而是由系统根据程序的需要即时分配,且分配的大小就是程序要求的大小。从以上动、静态内存分配比较可以知道动态内存分配相对于景泰内存分配的特点:&   1、不需要预先分配存储空间;   2、分配的空间可以根据程序的需要扩大或缩小。&& &&要实现根据程序的需要动态分配存储空间,就必须用到malloc函数.& &&malloc函数的原型为:void *malloc (unsigned int size) 其作用是在内存的动态存储区中分配一个长度为size的连续空间。其参数是一个无符号整形数,返回值是一个指向所分配的连续存储域的起始地址的指针。还有一点必须注意的是,当函数未能成功分配存储空间(如内存不足)就会返回一个NULL指针。所以在调用该函数时应该检测返回值是否为NULL并执行相应的操作。& &&静态内存是在程序一开始运行就会分配内存,直到程序结束了,内存才被释放。& &&动态内存是在程序调用在程序中定义的函数时才被分配,函数调用结束了,动态内存就释放。12345678910111213141516171819static&&&&&&&int&&&&&&&&&&/&例如&:jiechen(&int&i&){&&&&static&int&a&=&1;&&&&for&(;&a&&=&i,&a++&)&&&&&&&&return(a&*&i);}#include&"stdio.h"main(){&&&&int&a,&i;&&&&printf(&"enter&number:"&)&&&&scanf(&"%d",&&a&);&&&&for&(&i&=&1;&i&&=&a;&i++&)&&&&&&&&printf(&"i!=%d\n",&jiechen(&i&)&);}& &&运行& &&输入3& &&结果为1 ! = 12 ! = 23 ! = 3& &&由malloc系统函数分配的内存就是从堆上分配内存。从堆上分配的内存一定要自己释放。用free释放,不然就是术语——“内存泄露”(或是“内存漏洞”)—— Memory Leak。于是,系统的可分配内存会随malloc越来越少,直到系统崩溃。还是来看看“栈内存”和“堆内存”的差别吧。& & 栈内存分配123456&&&&char*&&&&AllocStrFromStack()&&&&{&&&&&&&&char&pstr[100];&&&&&&&&return&&&&&}&&&& & 堆内存分配12345678char*&AllocStrFromHeap(&int&len&){&&&&char&*&&&&&if&(&len&&=&0&)&&&&&&&&return(NULL);&&&&return(&(&char&*&)&malloc(&len&)&);}& &&& &&对于第一个函数,那块pstr的内存在函数返回时就被系统释放了。于是所返回的char*什么也没有。而对于第二个函数,是从堆上分配内存,所以哪怕是程序退出时,也不释放,所以第二个函数的返回的内存没有问题,可以被使用。但一定要调用free释放,不然就是Memory Leak!& &&在堆上分配内存很容易造成内存泄漏,这是C/C++的最大的“克星”,如果你的程序要稳定,那么就不要出现Memory Leak。所以,我还是要在这里千叮咛万嘱付,在使用malloc系统函数(包括calloc,realloc)时千万要小心。& &&记得有一个UNIX上的服务应用程序,大约有几百的C文件编译而成,运行测试良好,等使用时,每隔三个月系统就是down一次,搞得许多人焦头烂额,查不出问题所在。只好,每隔两个月人工手动重启系统一次。出现这种问题就是Memery Leak在做怪了,在C/C++中这种问题总是会发生,所以你一定要小心。一个Rational的检测工作——Purify,可以帮你测试你的程序有没有内存泄漏。& &&我保证,做过许多C/C++的工程的程序员,都会对malloc或是new有些感冒。当你什么时候在使用malloc和new时,有一种轻度的紧张和惶恐的感觉时,你就具备了这方面的修养了。对于malloc和free的操作有以下规则:1) 配对使用,有一个malloc,就应该有一个free。(C++中对应为new和delete)2) 尽量在同一层上使用,不要像上面那种,malloc在函数中,而free在函数外。最好在同一调用层上使用这两个函数。3) malloc分配的内存一定要初始化。free后的指针一定要设置为NULL。& &&注:虽然现在的操作系统(如:UNIX和Win2k/NT)都有进程内存跟踪机制,也就是如果你有没有释放的内存,操作系统会帮你释放。但操作系统依然不会释放你程序中所有产生了Memory Leak的内存,所以,最好还是你自己来做这个工作。(有的时候不知不觉就出现Memory Leak了,而且在几百万行的代码中找无异于海底捞针,Rational有一个工具叫Purify,可能很好的帮你检查程序中的Memory Leak)&& &&第一个例子也讲得不清楚。所谓系统释放,应该是指系统在自己的表里把这段内存标记为可以使用,以后可以被别的程序使用,所以第一个例子会造成程序能访问到已经释放的内存空间,是越界,会造成不可预测的情况。& &&系统一般不会自动去清除释放空间内的数据,而是由以后的程序来覆盖。所以很多程序开头都会做MEMSET(...) ,就是为了防止这种垃圾数据的情况。& &&如果在程序运行中要改变内存块的大小,可以用RALLOC()函数,它能在原来地址上重新分配一块空间,不过是用的时候要小心,也是比较容易出问题&
阅读(...) 评论()C/C++动态分配与释放内存的区别详细解析
字体:[ ] 类型:转载 时间:
以下是对C与C++中动态分配与释放内存的区别进行了详细的分析介绍,需要的朋友可以过来参考下
1. malloc()函数1.1 malloc的全称是memory allocation,中文叫动态内存分配。原型:extern void *malloc(unsigned int num_bytes); 说明:分配长度为num_bytes字节的内存块。如果分配成功则返回指向被分配内存的指针,分配失败返回空指针NULL。当内存不再使用时,应使用free()函数将内存块释放。
1.2 void *malloc(int size); 说明:malloc 向系统申请分配指定size个字节的内存空间,返回类型是 void* 类型。void* 表示未确定类型的指针。C,C++规定,void* 类型可以强制转换为任何其它类型的指针。   备注:void* 表示未确定类型的指针,更明确的说是指申请内存空间时还不知道用户是用这段空间来存储什么类型的数据(比如是char还是int或者...)
1.3 freevoid free(void *FirstByte): 该函数是将之前用malloc分配的空间还给程序或者是操作系统,也就是释放了这块内存,让它重新得到自由。
1.4注意事项1)申请了内存空间后,必须检查是否分配成功。
2)当不需要再使用申请的内存时,记得释放;释放后应该把指向这块内存的指针指向NULL,防止程序后面不小心使用了它。
3)这两个函数应该是配对。如果申请后不释放就是内存泄露;如果无故释放那就是什么也没有做。释放只能一次,如果释放两次及两次以上会出现错误(释放空指针例外,释放空指针其实也等于啥也没做,所以释放空指针释放多少次都没有问题)。4)虽然malloc()函数的类型是(void *),任何类型的指针都可以转换成(void *),但是最好还是在前面进行强制类型转换,因为这样可以躲过一些编译器的检查。
1.5& malloc()到底从哪里得到了内存空间?答案是从堆里面获得空间。也就是说函数返回的指针是指向堆里面的一块内存。操作系统中有一个记录空闲内存地址的链表。当操作系统收到程序的申请时,就会遍历该链表,然后就寻找第一个空间大于所申请空间的堆结点,然后就将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。
2. new运算符
2.1 C++中,用new和delete动态创建和释放数组或单个对象。动态创建对象时,只需指定其数据类型,而不必为该对象命名,new表达式返回指向该新创建对象的指针,我们可以通过指针来访问此对象。int *pi=这个new表达式在堆区中分配创建了一个整型对象,并返回此对象的地址,并用该地址初始化指针pi 。
2.2 动态创建对象的初始化动态创建的对象可以用初始化变量的方式初始化。int *pi=new int(100); //指针pi所指向的对象初始化为100string *ps=new string(10,'9');//*ps 为“”
如果不提供显示初始化,对于类类型,用该类的默认构造函数初始化;而内置类型的对象则无初始化。也可以对动态创建的对象做值初始化:int *pi=new int( );//初始化为0int *pi=//pi 指向一个没有初始化的intstring *ps=new string( );//初始化为空字符串 (对于提供了默认构造函数的类类型,没有必要对其对象进行值初始化)
2.3 撤销动态创建的对象delete表达式释放指针指向的地址空间。// 释放单个对象delete [ ]//释放数组如果指针指向的不是new分配的内存地址,则使用delete是不合法的。
2.4 在delete之后,重设指针的值 //执行完该语句后,p变成了不确定的指针,在很多机器上,尽管p值没有明确定义,但仍然存放了它之前所指对象的地址,然后p所指向的内存已经被释放了,所以p不再有效。此时,该指针变成了悬垂指针(悬垂指针指向曾经存放对象的内存,但该对象已经不存在了)。悬垂指针往往导致程序错误,而且很难检测出来。一旦删除了指针所指的对象,立即将指针置为0,这样就非常清楚的指明指针不再指向任何对象。(零值指针:int *ip=0;)
2.5 区分零值指针和NULL指针零值指针,是值是0的指针,可以是任何一种指针类型,可以是通用变体类型void*也可以是char*,int*等等。空指针,其实空指针只是一种编程概念,就如一个容器可能有空和非空两种基本状态,而在非空时可能里面存储了一个数值是0,因此空指针是人为认为的指针不提供任何地址讯息。
2.6 new分配失败时,返回什么?1993年前,c++一直要求在内存分配失败时operator&& new要返回0,现在则是要求operator&& new抛出std::bad_alloc异常。很多c++程序是在编译器开始支持新规范前写的。c++标准委员会不想放弃那些已有的遵循返回0规范的代码,所以他们提供了另外形式的operator&& new(以及operator&& new[])以继续提供返回0功能。这些形式被称为“无抛出”,因为他们没用过一个throw,而是在使用new的入口点采用了nothrow对象: class&& widget&& {&& ...&& };
widget&& *pw1&& =&& new&&//&& 分配失败抛出std::bad_alloc&&
if&& (pw1&& ==&& 0)&& ... //&& 这个检查一定失败
widget&& *pw2&& =&& new&& (nothrow)&&&& //&& 若分配失败返回0
if&& (pw2&& ==&& 0)&& ... //&& 这个检查可能会成功
3. malloc和new的区别
3.1 new 返回指定类型的指针,并且可以自动计算所需要大小。比如:   1) int *p;   p = //返回类型为int* 类型(整数型指针),分配大小为 sizeof(int);   或:   int*   parr = new int [100]; //返回类型为 int* 类型(整数型指针),分配大小为 sizeof(int) * 100;   
2) 而 malloc 则必须要由我们计算字节数,并且在返回后强行转换为实际类型的指针。   int*   p = (int *) malloc (sizeof(int)*128);//分配128个(可根据实际需要替换该数值)整型存储单元,并将这128个连续的整型存储单元的首地址存储到指针变量p中& double *pd=(double *) malloc (sizeof(double)*12);//分配12个double型存储单元,并将首地址存储到指针变量pd中
3.2 malloc 只管分配内存,并不能对所得的内存进行初始化,所以得到的一片新内存中,其值将是随机的。除了分配及最后释放的方法不一样以外,通过malloc或new得到指针,在其它操作上保持一致。
4.有了malloc/free为什么还要new/delete?
1) malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。
2) 对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。我们不要企图用malloc/free来完成动态对象的内存管理,应该用new/delete。由于内部数据类型的“对象”没有构造与析构的过程,对它们而言malloc/free和new/delete是等价的。
3) 既然new/delete的功能完全覆盖了malloc/free,为什么C++不把malloc/free淘汰出局呢?这是因为C++程序经常要调用C函数,而C程序只能用malloc/free管理动态内存。如果用free释放“new创建的动态对象”,那么该对象因无法执行析构函数而可能导致程序出错。如果用delete释放“malloc申请的动态内存”,结果也会导致程序出错,但是该程序的可读性很差。所以new/delete必须配对使用,malloc/free也一样。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具}

我要回帖

更多关于 动态分配 静态分配 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信