目录为什么会有动态内存分配动态内存函数的介绍malloc freecallocrealloc常见的错误对NULL指针的解引用操作越界访问对非动态内存进行free使用free
内存使用方式有两种
1.创建一个变量
2.创建一个数组
int a = 1;
int arr[10];
但是这两种方式都有一些特点
1.空间是固定大小的,不会变
2.必须提前知道要开辟多少空间,必须指定数组的长度。
但是实际上,对于空间的需求,有些时候,我们并不知道要分配多少内存空间,有时候需要在程序运行时才知道,比如用一个数组存放班级学生的年龄,我们不知道有多少个学生,不知道需要多大的空间,而且编译器又不支持变长的数组,应该是常量表达式。这时候,用数组分配固定的空间就不适合了。
为了更好地分配内存空间,这时候就需要我们的动态内存分配了。
说到内存,我们知道内存分为3个区域,栈区,堆区,静态区。
栈区——局部变量,函数形参
堆区——动态内存分配
静态区——全局变量,静态变量(如static int a = 10)
void *malloc( size_t size );
函数向堆区开辟一块连续的空间,返回空间的起始地址。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main()
{
int* p = (int*)malloc(10 * sizeof(int));
if (p == NULL)
{
//打印错误原因的一个方式
printf("%s\n", strerror(errno));
}
else
{
//正常使用
int i = 0;
for (i = 0; i < 10; i++)
{
*(p + i) = i;
}
for (i = 0; i < 10; i++)
{
printf("%d ", *(p+i));
}
}
//释放
free(p);
p = NULL;
return 0;
}
void free( void *memblock );
C语言提供一个函数free,专门用来动态内存的回收和释放的
头文件是#include <stdlib.h>
注意几点:
用于动态开辟的内存,如果不是的话,那free函数行为是未定义的
如果指针是NULL指针,则函数什么事都不做
被free后的指针最好手动置为NULL,避免野指针,造成错误
free(p);
p=NULL;
void *calloc( size_t num, size_t size );
calloc也是用来动态开辟空间。头文件也为#include <stdlib.h>
与malloc的区别:
参数不同
与malloc的区别只在于calloc会返回地址之前把申请的空间的每个字节初始化为0。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main()
{
//malloc(10*sizeof(int));
int*p = (int*)calloc(10, sizeof(int));
if (p == NULL)
{
printf("%s\n", strerror(errno));
}
else
{
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", *(p + i));
}
}
free(p);
p = NULL;
return 0;
}
调试一下,可以看到内存都初始化为0了
根据实际情况,如果需要初始化的话那就使用calloc
void *realloc( void *ptr, size_t size );
头文件也是引用#include <stdlib.h>
ptr是要调整的内存地址
size调整之后新大小,而不是增加的大小
返回值为调整之后的内存起始位置
realloc函数的出现让动态内存管理更加灵活
有时候我们发现申请的空间太小,有时候又会觉得申请过大了,为了合理的分配内存,我们可以对内存的大小做灵活的调整,realloc可以做到对动态内存大小的调整
注意事项
realloc在调整内存存在两种情况
情况1:原有空间之后有足够大的空间
情况2:原有空间之后没有足够的空间
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main()
{
int* p = (int*)malloc(20);
if (p == NULL)
{
printf("%s\n", strerror(errno));
}
else
{
int i = 0;
for (i = 0; i < 5; i++)
{
*(p + i) = i;
}
}
//在使用malloc开辟的20个空间
//假设这里20个字节不能满足我们的使用
//希望我们能有40个字节的空间
//这里就可以使用realloc来调整动态开辟的内存
int* ptr = realloc(p, 40);
if (ptr != NULL)
{
p = ptr;
int i = 0;
for (i = 5; i < 10; i++)
{
*(p + i) = i;
}
for (i = 0; i < 10; i++)
{
printf("%d ", *(p+ i));
}
}
free(p);
p = NULL;
return 0;
}
int main()
{
int* p = (int*)malloc(INT_MAX/4);
*p = 20;//如果p是空指针,就会有问题;
free(p);
return 0;
}
int* p = (int*)malloc(40);
if (p == NULL)
{
return 0;
}
int i = 0;
//越界
for (i = 0; i <= 10; i++)
{
*(p + i) = i;
}
free(p);
p = NULL;
应该是i<10
int a = 10;
int* p = &a;
free(p);
p = NULL;
int* p = (int*)malloc(40);
if (p == NULL)
{
return 0;
}
int i = 0;
for (i = 0; i < 10; i++)
{
*p++ = i;
}
free(p);
return 0;
p不在指向动态内存开辟的起始位置,我们应该重新定义一个指针来记住起始地址
int* p = (int*)malloc(40);
if (p == NULL)
{
return 0;
}
free(p);
free(p);
忘记释放动态开辟的内存,就会造成内存泄漏
while (1)
{
malloc(1);
Sleep(1000);
}
申请内存而不还,计算机的内存是有限的,内存将会被耗干
到此这篇关于c语言详解动态内存分配及常见错误的解决的文章就介绍到这了,更多相关c语言动态内存分配内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
--结束END--
本文标题: c语言详解动态内存分配及常见错误的解决
本文链接: https://www.lsjlt.com/news/146946.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
下载Word文档到电脑,方便收藏和打印~
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0