内存分配的过程中容易出现以下的错误:
1,内存未分配成功,却在程序中使用了,解决办法是:使用前先进行判断
2,内存分配成功后,未进行初始化,解决办法是:初始化为常量值
3,内存分配成功后,初始化后,对内存的使用超过了边界。解决办法:注意边界条件
4,使用分配的内存后忘记释放内存。解决办法:释放与申请相对应。
5,释放后继续使用内存,解决办法:释放后将指向内存的指针赋值为NULL
c语言中的内存分配:
C语言中采用malloc()和free()函数进行内存的分配和释放,当然还有其他内存分配的函数(calloc()和realloc())。此文只对malloc()和free()函数进行了讨论。
calloc()函数:void* calloc(size_t num, size_t size_of_element)
说明: 其中num为元素的个数,size_of_element为每个元素所占的空间大小,申请的空间大小为:num*size_of_element, 同时每个空间被初始化为零。
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int i;
int *pn=(int *)calloc(10,sizeof(int));
for(i=0;i<10;i++)
printf("%3d",*pn++);
printf("\n");
free(pn);
return 0;
}
realloc()函数: void* realloc(void* mem_address, size_t newsize)
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i;
int *pn=(int *)malloc(5*sizeof(int));
printf("%p\n",pn);
for(i=0;i<5;i++)
scanf("%d",&pn[i]);
pn=(int *)realloc(pn,10*sizeof(int));
printf("%p\n",pn);
for(i=0;i<5;i++)
printf("%3d",pn[i]);
printf("\n");
free(pn);
return 0;
} 说明: 按照newsize的大小申请一个空间,将原来数据从地址mem_address中拷贝到新的地方,释放原来的内存,同时返回指向新的内存的指针。 realloc失败的时候,返回NULL; realloc失败的时候,原来的内存不改变,不会释放也不会移动;传递给realloc的指针必须是先前通过malloc(), calloc(), 或realloc()分配的; 假如原来的内存后面还有足够多剩余内存的话,realloc的内存=原来的内存+剩余内存,realloc还是返回原来内存的地址;
假如原来的内存后面没有足够多剩余内存的话,realloc将申请新的内存,然后把原来的内存数据拷贝到新内存里,原来的内存将被free掉,realloc返回新内存的地址; 如果size为0,效果等同于free()。这里需要注意的是只对指针本身进行释放,例如对二维指针**a,对a调用realloc时只会释放一维,使用时谨防内存泄露。一、malloc()和free()的基本概念以及基本用法:
void * malloc(long NumBytes):该函数分配了NumBytes个字节,并返回了指向这块内存的指针。如果分配失败,则返回一个空指针(NULL)。在写代码的过程一定要对内存分配失败与否进行判断。
void free(void *FirstByte):该函数是将之前用malloc分配的空间还给程序或者是操作系统,也就是释放了这块内存,让它重新得到自由。
char *pChar = NULL;
pChar = (char *)malloc(10*sizeof(char));
if (NULL == pChar) //check the malloc()'s return
{
cout<<"memory failed!"<<endl;
exit(1);
}
//do something
free(pChar);
pChar = NULL;2 关于函数使用需要注意的一些地方: A、申请了内存空间后,必须检查是否分配成功。 B、当不需要再使用申请的内存时,记得释放;释放后应该把指向这块内存的指针指向NULL,防止程序后面不小心使用了它。 C、这两个函数应该是配对。如果申请后不释放就是内存泄露;如果无故释放那就是什么也没有做。释放只能一次,如果释放两次及两次以上会出现错误(释放空指针例外,释放空指针其实也等于啥也没做,所以释放空指针释放多少次都没有问题)。 D、虽然malloc()函数的类型是(void *),任何类型的指针都可以转换成(void*),但是最好还是在前面进行强制类型转换,因为这样可以躲过一些编译器的检查。3 深层次理解malloc()和free()
3.1、malloc()到底从哪里得到了内存空间?从堆里面获得空间。也就是说函数返回的指针是指向堆里面的一块内存。操作系统中有一个记录空闲内存地址的链表。当操作系统收到程序的申请时,就会遍历该链表,然后就寻找合适的空间(不同的内存管理办法采用不同的分配原则),然后就将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。就是这样!(具体的怎么去分配的可以看有关OS的书中内存管理的相关章节,内存管理有:分页式管理,分段式管理和两种方式结合)
3.2、什么是堆:堆是大家共有的空间,分全局堆和局部堆。全局堆就是所有没有分配的空间,局部堆就是用户分配的空间。堆在操作系统对进程初始化的时候分配,运行过程中也可以向系统要额外的堆,但是记得用完了要还给操作系统,要不然就是内存泄漏。什么是栈:栈是线程独有的,保存其运行状态和局部自动变量的。栈在线程开始的时候初始化,每个线程的栈互相独立。每个函数都有自己的栈,栈被用来在函数之间传递参数。操作系统在切换线程的时候会自动的切换栈,就是切换SS/ESP寄存器。栈空间不需要在高级语言里面显式的分配和释放。
栈是由编译器自动分配释放,存放函数的参数值、局部变量的值等。操作方式类似于数据结构中的栈。堆一般由程序员分配释放,若不释放,程序结束时可能由OS回收。注意这里说是可能,并非一定。所以我想再强调一次,记得要释放!注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。
void Function(void)
{
char *p = (char *)malloc(100 * sizeof(char));
} free(pChar);
pChar = NULL; //赋值为NULL4 malloc()以及free()的机制:
struct mem_control_block {
int is_available;
int size;//这是实际空间的大小
};void free(void *ptr)
{
struct mem_control_block *free;
free = ptr - sizeof(struct mem_control_block);
free->is_available = 1;
return;
}c++语言中的new和delete运算符
1. 开辟单变量地址空间
1)new int; //开辟一个存放数组的存储空间,返回一个指向该存储空间的地址.int *a = new int 即为将一个int类型的地址赋值给整型指针a.
2)int *a = new int(5) 作用同上,但是同时将整数赋值为5
2. 开辟数组空间
一维: int *a = new int[100];开辟一个大小为100的整型数组空间
二维: int **a = new int[5][6]
三维及其以上:依此类推.
一般用法: new 类型 [初值]
delete用法:
1. int *a = new int;
delete a; //释放单个int的空间
2.int *a = new int[5];
delete [] a; //释放int数组空间
要注意new和delete是一对,new[]和delete[]是一对。
要访问new所开辟的结构体空间,无法直接通过变量名进行,只能通过赋值的指针进行访问.
用new和delete可以动态开辟,撤销地址空间.在编程序时,若用完一个变量(一般是暂时存储的数组),下次需要再用,但却又想省去重新初始化的功夫,可以在每次开始使用时开辟一个空间,在用完后撤销它.
576

被折叠的 条评论
为什么被折叠?



