关于c语言内存分配,malloc,free,和段错误,内存泄露

1.   C语言的函数malloc和free

(1) 函数malloc和free在头文件<stdlib.h>中的原型及参数

       void * malloc(size_t size)

动态配置内存,大小有size决定,返回值成功时为任意类型指针,失败时为NULL。

void  free(void *ptr)

释放动态申请的内存空间,调用free()后ptr所指向的内存空间被收回,如果ptr指向未知地方或者指向的空间已被收回,则会发生不可预知的错误,如果ptr为NULL,free不会有任何作用。

(2) C语言中典型用法

T为任意数据类型

T *p = ( T * )malloc( sizeof(T) * n)

if(NULL= =p)

  {

printf(“malloc fail!\n”);

……//相关资源收回的处理

exit(-1);

  }

… …//此过程不能改变指针p的指向,如果改变指针指向,那么后面free将会出错,因为这里free的并不是原来的p指针,而是改变后的。当然如果改变了p的指向,那么必须再free前,将p再指回原来的位置。这样就没问题了。

free(p);

p=NULL;

注意:malloc后通常要对返回值进行判断,避免发生不必要的错误。

注意,最好再p 被free掉后,加上p=NULL这句

“野指针”不是NULL指针,是指向“垃圾”内存(不可用内存)的指针。人们一般不会错用NULL指针,因为用if语句很容易判断。但是“野指针”是很危险的,if无法判断一个指针是正常指针还是“野指针”。有个良好的编程习惯是避免“野指针”的唯一方法。

指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针。别看free和delete的名字(尤其是delete),它们只是把指针所指的内存给释放掉,但并没有把指针本身干掉。此时指针指向的就是“垃圾”内存。释放后的指针应立即将指针置为NULL,防止产生“野指针”。

(3) 内存说明

malloc函数动态申请的内存空间是在里(而一般局部变量存于栈里),并且该段内存不会被初始化,与全局变量不一样,如果不采用手动free()加以释放,则该段内存一直存在,直到程序退出才被系统,所以为了合理使用内存,在不适用该段内存时,应该调用free()。另外,如果在一个函数里面使用过malloc,最好要配对使用free,否则容易造成内存泄露(没有将内存还给自由存储区)。

但是,往往会在free的时候发生段错误.

正确的做法是这样:

// 在分配之前加一句判断指针是否为空,防止产生内存泄露

struct XXXX * ptr=NULL;
if (ptr == NULL) {
ptr  =  (struct XXXX *)malloc(num * sizeof(struct XXXX);

}

// 在释放之前加一句判断指针是否为空,防止产生异常
if (ptr != NULL) {
free(ptr);
ptr = NULL;

}

补充:C 语言作为 Linux 系统上标准的编程语言给予了我们对动态内存分配很大的控制权。


然而,这种自由可能会导致严重的内存管理问题,而这些问题可能导致程序崩溃或随时间的推移导致性能降级。

内存泄漏(即 malloc() 内存在对应的 free() 调用执行后永不被释放)和缓冲区溢出(例如对以前分配到某数组的内存进行写操作)是一些常见的问题,它们可能很难检测到。这一部分将讨论几个调试工具,它们极大地简化了检测和找出内存问题的过程。

只要在代码中添加一个头文件并在 gcc 语句中定义了 MEMWATCH 之后,您就可以跟踪程序中的内存泄漏和错误了。MEMWATCH 支持 ANSI C,它提供结果日志纪录,能检测双重释放(double-free)、错误释放(erroneous free)、没有释放的内存(unfreed memory)、溢出和下溢等等。

这里是memwatch的说明

补充2:转自:http://www.cnblogs.com/yfanqiu/archive/2012/05/08/2490410.html

2.  C++中的运算符new和delete

new和delete是C++中的运算符,不是库函数,不需要库的支持,同时,他们是封装好的运算符。

(1)new是动态分配内存的运算符,自动计算需要分配的空间,在分配类类型的内存空间时,同时调用类的构造函数对内存空间进行初始化,即完成类的初始化工作。动态分配内置类型是否自动初始化取决于变量定义的位置,在函数体外定义的变量都初始化为0,在函数体内定义的内置类型变量都不进行初始化。

(2)delete是撤销动态申请的内存运算符。delete与new通常配对使用,与new的功能相反,可以对多种数据类型形式的内存进行撤销,包括类,撤销类的内存空间时,它要调用其析构函数,完成相应的清理工作,收回相应的内存资源。

(3)典型用法

int *p = new int;                       delete p;

char *p = new char;                  delete p;

类的类型 *p = new 类的类型; delete p;

//注意,指针p存于栈中,p所指向的内存空间却是在堆中。

Obj * p = new Obj[100];                     delete [ ]p;

//注意,new申请数组,delete删除的形式需要加括号“[ ]”,表示对数组空间的操作,总之,申请形式如何,释放的形式就如何。

(4)内存说明。new申请的内存也是存于中,所以在不需要使用时,需要delete手动收回。

3.  new/delete与malloc/free之间的联系和区别

(1)          malloc/free和new/delete的联系

a)存储方式相同。malloc和new动态申请的内存都位于堆中。申请的内存都不能自动被操作系统收回,都需要配套的free和delete来释放。

b)除了带有构造函数和析构函数的类等数据类型以外,对于一般数据类型,如int、char等等,两组动态申请的方式可以通用,作用效果一样,只是形式不一样。

c)内存泄漏对于malloc或者new都可以检查出来的,区别在于new可以指明是那个文件的那一行,而malloc没有这些信息。

d)两组都需要配对使用,malloc配free,new配delete,注意,这不仅仅是习惯问题,如果不配对使用,容易造成内存泄露。同时,在C++中,两组之间不能混着用,虽说有时能编译过,但容易存在较大的隐患。

(2)          malloc/free和new/delete的区别

a)malloc和free返回void类型指针,new和delete直接带具体类型的指针。

b)malloc和free属于C语言中的函数,需要库的支持,而new/delete是C++中的运算符,所以new/delete的执行效率高些。C++中为了兼用C语法,所以保留malloc和free的使用,但建议尽量使用new和delete。

c)在C++中, new是类型安全的,而malloc不是。例如:

int* p = new char[10];                    // 编译时指出错误

delete [ ]p;                                     //对数组需要加中括号“[ ]”

int* p = malloc(sizeof(char )*10);    // 编译时无法指出错误

free (p);                                       //只需要所释放内存的头指针

d)使用new动态申请类对象的内存空间时,类对象的构建要调用构造函数,相当于对内存空间进行了初始化。而malloc动态申请的类对象的内存空间时,不会初始化,也就是说申请的内存空间无法使用,因为类的初始化是由构造函数完成的。delete和free的意义分别于new和malloc相反。

e)不能用malloc和free来完成类对象的动态创建和删除。

4.  C/C++程序的内存分配介绍

该部分参考于http://blog.csdn.net/sparkliang/archive/2008/12/30/3650324.aspx

(1)栈内存分配运算内置于处理器的指令集中,一般使用寄存器来存取,效率很高,但是分配的内存容量有限。一般局部变量和函数参数的暂时存放位置。

(2)堆内存,亦称动态内存。如malloc和new申请的内存空间。动态内存的生存期由程序员自己决定,使用非常灵活。

(3)全局代码区:从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。

(4)常量区:文字常量分配在文字常量区,程序结束后由系统释放。

(5)代码区:存放整个程序的代码,因为存储是数据和代码分开存储的。

总结:

(1)new、delete 是操作符,只能在C++中使用。malloc、free是函数,可以覆盖,C、C++中都可以使用。
(2)new 自动计算需要分配的空间大小,可以调用对象的构造函数,对应的delete调用相应的析构函数。malloc仅仅分配内存,free仅仅回收内存,并不执行构造和析构函数
(3)new 类型安全、返回的是某种数据类型指针,malloc 非类型安全、返回的是void指针。
时间: 2024-10-10 14:51:30

关于c语言内存分配,malloc,free,和段错误,内存泄露的相关文章

c语言中的内存分配malloc、alloca、calloc、malloc、free、realloc、sbr

C语言跟内存分配方式 (1) 从静态存储区域分配.内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量,static变量. (2) 在栈上创建.在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放.栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限. (3)从堆上分配,亦称动态内存分配.程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存.动态内存的

C语言中的动态内存分配,malloc/free

malloc函数 原型 extern void *malloc(unsigned int num_bytes); 头文件 #include <stdlib.h> 功能 分配长度为num_bytes字节的内存块 返回值 如果分配成功则返回指向被分配内存的指针(此存储区中的初始值不确定),否则返回空指针NULL.当内存不再使用时,应使用free()函数将内存块释放.函数返回的指针一定要适当对齐,使其可以用于任何数据对象. 说明 关于该函数的原型,在以前malloc返回的是char型指针,新的ANS

Linux-(C/C++)动态内存分配malloc以及相关学习

1.C/C++内存分类(引用C++ Primer )(对象在C语言中可以理解为变量) 1.1.静态内存:静态内存用来保存局部static对象.类static数据成员.以及定义在任何函数之外的变量 1.2.栈内存:栈内存用来保存定义在函数内非static对象.(当然包含函数参数开辟的内存) 1.3.动态内存:每个程序还有一个内存池,这部分内存被称作自由空间(free store)或者堆(heap).程序用堆来存储动态分配的内存(dynamically allocate)的对象,也就是,那些在程序运

[转]内存分配malloc, new , heapalloc

这里比较的VC++编译的C++代码中的性能 我用的是VC6.0测试的 就不介绍这几个的用法了 我写了一段简单的测试代码 测试结果是: malloc:390new:391VirtualAlloc:454HeapAlloc:47 很明显的是HeapAlloc分配速度最快,malloc次之,new和malloc差不多,VirtualAlloc最慢了(以前小强跟我说这个最快) 我有跟踪了一下 new调用了这段代码 void * __cdecl _nh_malloc ( size_t nSize, int

c语言内存分配-malloc

malloc 原型:(原来返回类型是char) 1 extern void *malloc(unsigned int num_bytes); 头文件: 1 #include <stdlib.h> 2 #include <malloc.h> 函数声明: void *malloc(size_t size); 返回值: 分配成功:返回被分配内存的指针 失败:返回NULL 不再使用时,可用free()函数释放内存 使用: 1 int *p,*s; 2 p=(int*)malloc(size

数据结构-c语言内的内存分配

常用到的数据存储区: 在C语言中,根据数据在内存中存在的时间(生存期)不同,将内存空间分为三个区: 1.程序区:用于存储程序的代码,即程序的二进制代码: 2.静态存储区:用于存储全局变量和静态变量,这些变量的空间在程序编译时就已经分配好了: 3.动态存储区:用于在程序执行时分配的内存,又分为:堆区(heap)和堆栈区(stack)两种. 堆区:用于动态内存分配,程序运行时由内存分配函数在堆上分配内存.在C语言中,只要使用指针才能动态的分配内存. 堆栈区:在函数执行时,函数内部的局部变量和函数参数

malloc的内存分配原理

0 堆内存的在计算机内存中的形式 根据<The C Programming language>推测得到堆内存,图中的Heap区域即为堆内存块(Heap区域的数目不代表计算机堆内存的真实数目). [1] 堆内存不连续.只有标识为Heap的才是堆内存. [2]  在malloc()/free()看来,每个Heap所代表的的堆由两部分组成:Header +可给用户使用的堆内存.在Header中包含了“指向下一邻近高地址堆内存块的指针”.“本堆块的大小”.每次由malloc()函数分配给用户的堆内存也

内存分配方式和调试机制

内存分配方式和调试机制 M内存分配 内存分配函数 MFCWin32或者C语言的内存分配API,有四种内存分配API可供使用. Win32的堆分配函数 每一个进程都可以使用堆分配函数创建一个私有的堆──调用进程地址空间的一个或者多个页面.DLL创建的私有堆必定在调用DLL的进程的地址空间内,只能被调用进程访问. HeapCreate用来创建堆:HeapAlloc用来从堆中分配一定数量的空间,HeapAlloc分配的内存是不能移动的:HeapSize可以确定从堆中分配的空间的大小:HeapFree用

数据结构中的堆和栈 与 内存分配中的堆区和栈区 分析

比較全面的总结了诸多版本号,知识无国界.感谢各位的辛勤劳作. 在计算机领域,堆栈是一个不容忽视的概念,我们编写的C/C++语言程序基本上都要用到.但对于非常多的初学着来说,堆栈是一个非常模糊的概念. (1) 数据结构的栈和堆 首先在数据结构上要知道堆栈,虽然我们这么称呼它,但实际上堆栈是两种数据结构:堆和栈. 堆和栈都是一种数据项按序排列的数据结构. 栈就像装数据的桶或箱子 我们先从大家比較熟悉的栈说起吧.它是一种具有后进先出性质的数据结构,也就是说后存放的先取.先存放的后取.这就如同我们要取出