动态内存管理
p在内存中申请的40个字节空间,这个指针p指向的内存的起始地址
所谓动态内存管理就是随便更改开辟内存空间的大小
//malloc函数
int main()
{
int* p = (int*)malloc(10 * sizeof(int));
if (p == NULL)
{
perror("malloc");
return 1;
}
for (int i = 0; i < 10; i++)
{
p[i] = i;
}
for (int i = 0; i < 10; i++)
{
printf("%d ", p[i]);
}
printf("\n");
return 0;
}
//动态内存管理 #include <stdlib.h> #include <errors.h> int main() { int* p = (int*)malloc(40); if (p == NULL) { printf("%s\n", strerror(errno)); } int i = 0; for (i = 0; i < 10; i++) { *(p + i) = i; } for (i = 0; i < 10; i++) { printf("%d ", *(p + i) ); } return 0; }
与malloc相匹配的函数是free
malloc是开辟堆区的函数,free是释放堆区的函数,
不用的时候要释放堆区,然后赋给空指针,否则就成为了野指针。
free函数只是释放的指针的空间,还给的操作系统,但是p还记录着之前的那个起始地址,所有指针p现在很危险,如果不置位空指针,那么就很可能成为野指针
malloc函数只是帮你申请空间,但是没有帮你初始化
你要释放哪个空间,就把那个起始地址传给free函数即可
calloc是开辟好了直接初始化,malloc是开辟了重新初始化。
如果已经通过了malloc或者calloc函数获得了动态空间,想改变其大小,可以用recalloc函数程序分配
情况1
当是情况1的时候,要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发⽣变化。
情况2
当是情况2的时候,原有空间之后没有⾜够多的空间时,扩展的⽅法是:在堆空间上另找⼀个合适⼤⼩的连续空间来使⽤。这样函数返回的是⼀个新的内存地址。
由于上述的两种情况,realloc函数的使⽤就要注意⼀些
realloc函数里为空指针 等价于malloc
常⻅的动态内存的错误
1. 对NULL指针的解引⽤操作
void test()
{
int* p = (int*)malloc(INT_MAX / 4);
if (p != NULL)///如果p的值是NULL,就会有问题
{
*p = 20;
}
else
{
perrer("malloc");
return 0;
}
free(p);
p= NULL;
}
2.对动态开辟空间的越界访问
void test()
{
int i = 0;
int* p = (int*)malloc(10 * sizeof(int));
if (NULL == p)
{
exit(EXIT_FAILURE);
}
for (i = 0; i < 10; i++)
{
*(p + i) = i;
}
free(p);
}
3. 对⾮动态开辟内存使⽤free释放
void test()
{
int* p = (int*)malloc(40);//在堆区申请空间
free(p); //空间释放
}
4. 使⽤free释放⼀块动态开辟内存的⼀部分
指针p指向的起始地址+1的地址,我们知道free释放是从起始地址开始释放的
4.5 对同⼀块动态内存多次释放
正确写法
4.6 动态开辟内存忘记释放(内存泄漏)
忘记切记:动态开辟的空间⼀定要释放,并且正确释放释放不再使⽤的动态开辟的空间会造成内存泄漏。