C语言——动态内存管理入门
动态内存管理
一.动态内存的意义。
我们之前能够分配内存的方式有:直接定义变量或者开辟一个固定大小的数组。
int a=10;
int a[10];
上述开辟内存的方式都是在栈内,并且是在编译时分配。
但是我们通常所需的看空间都是在运行时才知道,此时就需要动态开辟内存了。
2.接下来看看计算机中内存的划分。这是在Linux下的内存分布情况。
先展示一段代码来表示这些变量在内存中的存储情况:
#include <stdio.h>
#include <stdlib.h>
//定义一个函数
void A(){
;
}
int global=0;//定义一个全局变量
int main(){
int* p=(int *)malloc(sizeof(int)); //用malloc动态开辟一段内存空间
int a; //定义一个局部变量
printf("funcA=%p\n",A);
printf("global=%p\n",global);
printf("p=%p\n",p);
printf("&a=%p\n",&a);
return 0;
}
结果如下:Linux下。
从执行结果可以看出:函数、全局变量、动态开辟的空间、局部变量的地址就如上图那样从高到低。
三.几种动态分开辟内存的方式
1.malloc与free
函数原型:
void* malloc(size_t size);
void free(void * ptr);
malloc所开辟的空间是在堆上分配的,堆上的空间比栈要大很多,但是也是有限度的。
当malloc分配空间成功时,会返回开辟成功的空间的地址,分配失败,则会返回NULL;
int *p = (int*)malloc(sizeof(int));
*p = 444;
printf("%p,%d\n", p, *p);
free(p);
printf("%p\n", p);
运行结果:
注意:
(1).malloc后必须free,否则就会内存泄漏。
(2).free后的空间并没有指向空,只是将那段空间的值释放了。
(3).malloc的变量不能多次free,只能free一次,否则还是内存泄漏。
(4).为了避免这种访问到已经free的内存,我们可以在free后就让指针变量指向NULL。这样一旦对空指针解引用,我们就会很快的发现错误。
(5).一般对malloc所开辟的空间都需要进行成功与否的判断,如果分配失败它就会返回一个空指针。
2.calloc
函数原型:
void* calloc(size_t num, size_t size);
函数功能:为num个大小是size的元素开辟一块空间,并且将空间的每个字节都初始化为0;
int *p = calloc(10, 4);
printf("%d\n", *p);
int *pp = (int *)malloc(sizeof(int)*10);
printf("malloc时候:%p\n", pp);
pp = realloc(pp, 500);
if (pp == NULL) {
printf("realloc时候:pp是空!!!\n");
}
else {
printf("realloc时候:pp非空!!!\n%p\n",pp);
}
执行结果:
3.realloc
函数原型:
void* realloc(void* ptr, size_t size);
函数功能:扩容:
如果原有空间有足够的空间,那么就玩原来的空间后面直接“续”。
如果原有空间后面没有足够的空间,就新开辟一段空间。
总结:
1.malloc与free,malloc必须free
2.动态分配内存不忘判断是否分配成功。