C语言复习:动态内存管理

创建一个变量
int a=10;//创建的是局部变量 ——栈区
int m_a =10; //创建的是全局变量 ——静态区
创建一个数组
int arr[10];——栈区
动态内存分配在堆区开辟空间。
1

malloc函数的使用

使用前提:头文件要加<stdlib.h>

int main()
{
     int *p=(int*)malloc(10*sizeof(int));//向内存申请10个整型空间
     if(p==NULL)
     {
      printf("申请失败";
     }
     else
     {
          //正常使用空间;
     }
     free(p);//当动态申请的空间不再使用要归还给操作系统
     p=NULL;
     return 0;
}

free 专门用来做动态内存的释放和回收
void free(void* memblock)
free只释放动态开辟的,若free(NULL)没有什么影响相当于啥也没干。
malloc要和free配套使用。
若malloc申请空间成功则返回一个void*,失败则返回NULL指针。

void malloc(size_t size);
向内存申请一块连续
可用的空间,并返回指向这块空间的指针

  1. 若开辟成功,则返回一个指向开辟好空间的指针
  2. 若开辟失败,返回NULL指针。由此可见使用malloc的时候一定要对返回值做检查(返回的是否为空指针)
  3. 开辟的空间类型由自己决定
  4. 如果参数size为0,malloc的行为的标准是未定义的。

calloc函数的使用

void* calloc(size_t num,size_t size);
num为元素的个数,size为字节数。

例如:开辟10个int类型元素的动态内存
calloc(10,sizeof(int));
int *p =(int *)calloc(10,sizeof(int));
也要使用free释放

realloc函数的使用

realloc——调整动态内存开辟大小
1.用malloc开辟20个字节的空间

int main()
{
 int *p =int*)malloc(20);
 if(p==NULL)
 {
  printf("%s\n",strerror(errno));//打印错误报告
 }
 else
 {
  int i=o;
  for(i=0;i<5;i++)
  {
   *(p+i)=i;
  }
 }

此时假设20个字节不能满足使用现需要40个字节的空间这时使用realloc调整动态开辟的内存
int *p=realloc(p,40);

vid* realloc(void* memblock,size_t size);
memblock之前所指的内存指针(需要调整大小的)
size字节大小

relloc使用注意事项
1.若原空间后还够用直接在后面加后返回p。
2.若不够用则需开辟一块满足需求的空间,并把原来内存中的数据拷贝回来,释放旧的内存空间最后返回新开辟的内存。

int *ptr=realloc(p,INT_MAX);
if(ptr!= NULL)
{
 p=ptr;//若没有开辟失败仍用指针p来维护开辟的内存空间
}

3.要用一个新的变量来接收realloc函数的返回值
情况1:扩展内存直接原有内存之后追加空间,原来空间的数据不发生改变
情况2:原空间之后没有足够大的空间
2
若int *p=realloc(NULL,40);相当于malloc(40);

常见的动态内存错误
1.对空指针解引用操作

2.对动态开辟的内存的越界访问
例如:

 int *p=(int*)malloc(5*sizeof(int)); //只开辟了5个整型空间
 if(p==NULL)
 {
  return 0;
 }
 else
 {
  int i=0;
  for(i=0;i<10;i++) //但却想访问10个,此时造成了越界访问内存
   {
     *(p+i)=i;
   }
 }
 free(p);
 p==NULL;
 return 0;
}

3.对非动态内存使用free释放

4.使用free释放动态开辟内存的一部分

5.对同一块动态内存的多次释放
要求我们在打代码的过程中要做到 谁申请谁释放
还可以free完以后直接置空即使后面不小心再释放一次也不影响最终结果
例如:
free§;
p=NULL;
free§;

6.对动态开辟内存忘记释放(内存泄漏)
内存泄漏简单来说就是会产生一直在申请内存一直不回收的现象

经典笔试题——找出开辟动态内存的问题

(一)

void GetMemory(char *p)
{
 p=(char *)malloc(100);
}
void Test(void)
{
 char *str=NULL;
 GetMemory(str);
 strcpy(str,"hello word");
 printf(str);
}

int main()
{
 Test();
 return 0;
}

问:该程序结果是什么?
1.运行代码会出现崩溃的现象
2.程序会存在内存泄漏的问题
如何分析该代码?
1
str以值传递的形式给p,p是GetMemory函数的形参,只对函数内部有效等GetMemory函数返回之后开辟内存尚未释放并且无找到,所以会造成内存泄漏。取地址才能传址
那么如何修改上述代码?
改正①

void GetMemory(char **p)
{
  *p=(char*)malloc(100);
}
void Test(void{
 char *str=NULL;
 GetMemory(&str);
 strcpy(str,"hello world");
  printf(str);
  
  free(str);
  str=NULL;
}

int main()
{
 Test();
 return 0;
}

修改②

char* GetMemory(char **p)
{
  p=(char*)malloc(100);
  return p; //记住p的地址再传递给str
}
void Test(void{
 char *str=NULL;
 str=GetMemory(str);
 strcpy(str,"hello world");
  printf(str);
  free(str);
  str=NULL;
}

int main()
{
 Test();
 return 0;
}

(二)

char *GetMemory(void)
{
  char p[]="hello world";
  return p;//返回p数组的地址
}
void Test(void)
{
  char *str=NULL;
  str=GetMemory(); //将p的地址记住返回给str但此时p已经不在
  printf(str); 
}
int main()
{
  Test();
  return 0;
}

上述代码会出现什么问题?
打印随机值(返回栈空间地址的问题)
空间已不在,任何都可以修改该地址的内容所以存在非法访问内存问题

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值