2021-06-28 C语言内存管理(续1)

堆栈、静态存储区
堆栈就是指栈,堆就是堆。内存可以分为3个区:堆、栈、静态存储区
静态存储区:存储的是程序里的全局变量与Static修饰的局部变量或全局变量。静态区的内容在程序的整个生命周期内都是 存在的,由编译器在编译的时候分配。
栈:栈是指保存的局部变量,栈里的内容只能在函数范围内存在,函数运行结束,这些局部变量就是自动销毁,其特点是效率高,但是空间大小有限。
堆:堆是由malloc或者new函数分配的内存,生命周期由Delete或者free函数决定,在没有释放之前是一直存在的,直到程序结束。其特点是使用灵活,但是容易出错,内存泄漏或者内存越界。

常见的错误:

struct student
{
char *name;
int score;
}stu,*pstu;
intmain()
{
strcpy(stu.name,"Jimy");
stu.score = 99;
return 0;
}

这里定义了结构体变量stu,但是他没想到这个结构体内部char *name 这成员在定义结构体变量stu 时,只是给name 这个指针变
量本身分配了4 个字节。name 指针并没有指向一个合法的地址,这时候其内部存的只是一些乱码。所以在调用strcpy 函数时,会将字符串"Jimy"往乱码所指的内存上拷贝,而这块内存name 指针根本就无权访问,导致出错。解决的办法是为name 指针malloc 一块空间。

intmain()
{
pstu = (struct student*)malloc(sizeof(struct student));
strcpy(pstu->name,"Jimy");
pstu->score = 99;
free(pstu);
return 0;
}

为指针变量pstu 分配了内存,但是同样没有给name 指针分配内存。错误与上面第一种情况一样,解决的办法也一样。这里用了一个malloc 给人一种错觉,以为也给name 指针分配了内存。

没有为结构体指针分配足够的内存
为指针分配的内存太小 为指针分配了内存,但是内存大小不够,导致出现越界错误。

char *p1 = “abcdefg”;
char *p2 = (char *)malloc(sizeof(char)*strlen(p1));
strcpy(p2,p1);

p1 是字符串常量,其长度为7 个字符,但其所占内存大小为8 个byte。初学者往往忘了字符串常量的结束标志“\0”。这样的话将导致p1 字符串中最后一个空字符“\0”没有被拷贝到p2 中。解决的办法是加上这个字符串结束标志符:
char *p2 = (char *)malloc(sizeof(char)strlen(p1)+1sizeof(char));

内存分配成功,但并未初始化

int i = 10char *p = (char *)malloc(sizeof(char))

但是往往这个时候我们还不确定这个变量的初值,这样的话可以初始化为0 或NULL。

int i = 0char *p = NULLint a[10] = {0};

内存越界****内存泄漏
使用malloc 函数。使用malloc函数同样要注意这点:如果所申请的内存块大于目前堆上剩余内存块(整块),则内存分配
会失败,函数返回NULL。注意这里说的“堆上剩余内存块”不是所有剩余内存块之和,因为malloc 函数申请的是连续的一块内存。、

if(NULL != p)语句来验证内存确实分配成功

free 完之后,一定要给指针置NULL
既然使用free 函数之后指针变量p 本身保存的地址并没有改变,那我们就需要重新把p的值变为NULL:
p = NULL;这个NULL 就是我们前面所说的“栓野狗的链子”。如果你不栓起来迟早会出问题的。比如:在free(p)之后,你用if(NULL != p)这样的校验语句还能起作用吗?
例如:
char p = (char )malloc(100);
strcpy(p, “hello”);
free§; /
p 所指的内存被释放,但是p 所指的地址仍然不变
/

if (NULL != p)
{
/* 没有起到防错作用*/
strcpy(p, “world”); /* 出错*/
}
释放完块内存之后,没有把指针置NULL,这个指针就成为了“野指针”,也有书叫“悬垂指针”。这是很危险的,而且也是经常出错的地方

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值