常见的动态内存错误

  • 对NULL指针的解引用操作
void test()
{
int *p=(int*)malloc(INT_MAX/4);
*p=20; //如果p的值是NULL,就会有问题
free(p);//malloc开辟空间失败——对NULL指针解引用
}
  • 对动态内存开辟空间越界访问
void test()
{
int i=0;
int *p=(int*)malloc(10*sizeof(int));
if(NULL==p)
{
exit(EXIT_FAILURE);
}
for(i=0;i<=10;i++)  //当i=10时,越界访问
{
*(p+i)=i;
}
free(p);
}
  • 对非动态开辟内存使用free释放
{
int a=10;
int *p=&a;
free(p);//error
}
  • 使用free释放一块动态开辟内存的一部分
{
int *p=(int*)malloc(100);
p++;
free(p);//p不再指向动态内存的起始位置
}


*int p=realloc(NULL,40)<=>malloc(40)

  • 对同一块动态内存多次释放
{
int *p=(int*)malloc(100);
free(p);
//p=NULL;  //若p=NULL,后面的free也就无意义了
free(p);    //重复释放
}
  • 动态开辟内存忘记释放(内存泄漏)
#include<windows.h>
while(1)
{
malloc(1);
}
return 0;
}

问:运行Test函数是什么结果?

void GetMemory(char*p) // p是str的一份临时拷贝
{
p=(char*)malloc(100);
}
void Test(void)
{
char *str=NULL;
GetMemory(str);  //不管是指针变量还是其它变量,仅是传值
strcpy(str,"hello");
printf(str);
}
int main()
{Test();
return 0;
}

答:1.运行代码程序出现崩溃的现象
2.程序存在内存泄漏问题
分析:
str以值传递的形式给p,p是GetMemory函数的形参,只能函数内部有效,等GetMEmory函数返回值后,动态内存开辟尚未释放并且无法找到,所以会造成内存泄漏。

改正

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

在这里插入图片描述
改正2

char* GetMemory(char*p)
{
p=(char*)malloc(100);
return p;//出函数时,返回p,用str接收p地址
}
void Test(void)
{
char *str=NULL;
str=GetMemory(str);
strcpy(str,"hello");
printf(str);
free(str);
str=NULL;
}
int main()
{
Test();
return 0;
}

下面看在栈区,堆区,静态区返回地址的问题

char* GeMemory(void)
{
char p[]="hello";//局部变量
return p;
}
void Test(void)
{
char *str=NULL;
str=GetMemory();//非法访问内存空间
printf(str);
}
int mian()
{
Test();
return 0;
}
int *test()
{
int *ptr=malloc(100);
return ptr;
}
int main()
{
int *p=test();
return 0;
}//堆区不free就不会销毁地址
int *test()
{
static int a=10;  //静态区数据不会丢
return &a;
}
int mian()
{
int *p=test();
*p=20;//修改a的值为20
return 0;
}

完毕

int f2(void)——野指针
{
int
ptr;——ptr没有初始化,是一个随机值,对其进行解引用会形成非法访问内存
*ptr=10;
return ptr;
}

运行以下Test函数会有什么样的结果?

void Test(void)
{
char *str=(char*)malloc(100);
strcpy(str,"hello");
free(str);//free释放str指向的空间后,并不会把str置为NULL
if(str!-NULL)//判断有意义
{
strcpy(str,"World");
printf(str);
}
}
int main()
{
Test();
return 0;
}

答:篡改动态内存区的内容,后果难以预料,非常危险;
因为free(str)之后,str成为野指针,if(str!=NULL)语句不起作用。

C/C++程序内存分配的几个区域

  1. 栈区:在执行函数时,函数局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。栈区主要存放运行函数而分配的局部变量,函数参数,返回数据,返回地址等。
  2. 堆区;一般由程序员分配释放,若程序员不释放,程序结束后可能由0S操作系统回收。分配方式类似于链表
  3. 数据段:静态区存放全局变量,静态数据。程序结束后由系统释放
  4. 代码段:存放函数体(类成员函数和全局函数)的二进制代码

static关键字修饰局部变量例子
普通的局部变量实在栈区分配空间的,栈区的特点是在上面创建的变量出了作用域就销毁;
但被static修饰的变量存放在数据段,数据段的特点是在上面创建的变量,直到程序结束才销毁,所以生命周期变长。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值