<<C语言深度剖析>>学习笔记之六之内存管理
来源:互联网 发布:淘宝零食店策划书 编辑:程序博客网 时间:2024/06/06 00:15
C语言和内存打交道比较多的莫过于指针了.
1.野指针:
为防止野指针的出现,需要养成良好的编程习惯--指针要时刻要有明确的指向对象,否则其随机指向一块内存区域,哪个地址再引用就会引发莫名的BUG.为避免野指针,规范的编程习惯如下:
定义指针时初始化为NULL;指针用完后还是赋值为NULL.
2.内存的三个部分
内存可以分为三个部分:静态区、栈、堆.
2-1.静态区:保存自动全局变量和static变量(包括static全局和局部变量).静态区的内容在总个程序的生命周期内都存在,由编译器在编译的时候分配.
2-2.栈:保存局部变量.栈上的内容只在函数的范围内存在,当函数运行结束,这些内容也会自动被销毁.其特点是效率高,但空间大小有限.
2-3.堆:由malloc系列函数或new操作符分配的内存.其生命周期由free或delete决定.在没有释放之前一直存在,直到程序结束.其特点是使用灵活,空间比较大,但是容易出错.
3.常见的内存错误及对策.
3-1.指针没有指向一块合法的内存.
主要是指指针没有初始化.如下面这个示例:
#include <stdlib.h>#include <stdio.h>#include <string.h>typedef struct __student{ char *name; int age;}student,*pstudent;int main(int argc,char **argv){ student stu; strcpy(stu.name,"Se7en"); stu.age = 24; printf("stu.name = %s\n",stu.name); printf("stu.age = %d\n",stu.age); return 0;}输出结果:
root@seven-laptop:~/learn/C_Program# ./initpoint Segmentation faultroot@seven-laptop:~/learn/C_Program# vim initpoint.c
可见报段错误了.原因分析如下:
1).我们在定义stu这个结构体变量时,只为这个结构体内部name成员本身分配了4个字节,它并不一定指向一块合法的地址,它内部存放的只是一些乱码;
2).调用strcpy往这个乱码地址存放数据是危险的,因为很有可能这块地址是它无权访问的.
因此,当我们操作一个指针时.一定要明确这个指针指向哪!!!!
将上述代码达到我们预期的输出结果,可以通过下面两种方式实现.
方式一:
#include <stdlib.h>#include <stdio.h>#include <string.h>typedef struct __student{ char *name; int age;}student,*pstudent;int main(int argc,char **argv){ student stu;// strcpy(stu.name,"Se7en"); stu.name = "Se7en"; stu.age = 24; printf("stu.name = %s\n",stu.name); printf("stu.age = %d\n",stu.age); return 0;}输出结果:
root@seven-laptop:~/learn/C_Program# ./initpoint stu.name = Se7enstu.age = 24root@seven-laptop:~/learn/C_Program# vim initpoint.c分析:这时stu.name是指向"Se7en"这个字符串的.编译器为这个字符串分配的地址肯定是合法的.
方式二:
#include <stdlib.h>#include <stdio.h>#include <string.h>typedef struct __student{ char *name; int age;}student,*pstudent;int main(int argc,char **argv){ student stu; stu.name = (char *)malloc(sizeof(char) * 50); strcpy(stu.name,"Se7en"); stu.age = 24; printf("stu.name = %s\n",stu.name); printf("stu.age = %d\n",stu.age); free(stu.name); return 0;}输出结果:
root@seven-laptop:~/learn/C_Program# ./initpoint stu.name = Se7enstu.age = 24root@seven-laptop:~/learn/C_Program# vim initpoint.c
上述两种修改方式都是保证了我们要访问的stu.name指针有明确的指向.
3-2.assert()宏
被调用的函数经常参数是指针类型的.很多代码中都可以看到其使用assert()宏来判断传入的参数的合法性.assert()宏的意义如下:
assert()括号内的内容为假则终止程序并提示出错;为真则继续运行后面的代码.
因此,我们常用如下形式来判定传入的指针参数的合法性.
assert(NULL != p);
3-3.小心strlen()函数
我们常用strlen()来计算一个字符串的长度,strlen()计算出来的长度是不包括"\0"的.因此需要分配多一个字节.示例:
#include <stdio.h>#include <stdlib.h>#include <string.h>int main(int argc,char **argv){ char *pStr = "HelloWorld!"; char *q = NULL; printf("strlen(pStr) = %d\n",strlen(pStr)); q = (char *)malloc(sizeof(char) * strlen(pStr)); strcpy(q,pStr); printf("strlen(q) = %d\n",strlen(q)); printf("%s\n",pStr); printf("%s\n",q); free(q); q = NULL; return 0;}上述代码在GCC 4.2.2可以正常输出:
root@seven-laptop:~/learn/C_Program# ./malloc strlen(pStr) = 11strlen(q) = 11HelloWorld!HelloWorld!root@seven-laptop:~/learn/C_Program# vim malloc.c但是在VC6.0下运行报错.要在VC6.0正常运行并兼容GCC.代码修改如下:
#include <stdio.h>#include <stdlib.h>#include <string.h>int main(int argc,char **argv){ char *pStr = "HelloWorld!"; char *q = NULL; printf("strlen(pStr) = %d\n",strlen(pStr)); q = (char *)malloc(sizeof(char) * strlen(pStr) + 1 * sizeof(char)); strcpy(q,pStr); printf("strlen(q) = %d\n",strlen(q)); printf("%s\n",pStr); printf("%s\n",q); free(q); q = NULL; return 0;}输出结果:
root@seven-laptop:~/learn/C_Program# ./malloc strlen(pStr) = 11strlen(q) = 11HelloWorld!HelloWorld!root@seven-laptop:~/learn/C_Program# vim malloc.c可见,GCC对代码前后的输出结果是一样的.
总而言之,如果要存放一个字符串,记得多分配一个字节就是了.
3-4.malloc()函数注意检查返回值.
malloc()函数意为从堆上分配出一块内存以供程序使用,但是内存分配有可能是失败的.因此,一定要检查其返回值.如下:
char *p = (char )malloc(1024);if(NULL == p) { //内存申请失败处理. }
3-5.free()之后的故事
free()函数就是把这块内存和p之间的所有关系断开.它要和malloc必须一一对应.这时候特别注意的是,指针变量p本身保存的地址并没有改变,我们需要重新把p的值变为NULL.如下:
free(p);p = NULL;
- <<C语言深度剖析>>学习笔记之六之内存管理
- unix c 学习笔记之内存管理
- OBject-C 学习笔记之内存管理
- c语言学习笔记之内存分区
- c语言学习笔记24之内存
- C语言之内存管理
- C语言之内存管理
- C语言之内存管理
- C语言之内存管理
- c语言之内存管理
- C语言之内存管理
- C语言深度剖析笔记(六)
- 《C语言深度剖析》学习笔记----内存管理(2)
- 学习笔记之内存管理
- C语言学习之内存管理函数malloc()和free()
- C语言学习之内存管理函数malloc()和free()
- C语言学习之内存管理函数malloc()和free()
- 黑马程序员-----oc语言学习笔记之内存管理一
- Qevent
- 关于PhoneGap
- PROGRAMMING IN C++ Nell Dale Chip Weems
- 数组里的正数和负数排序
- 常见排序算法总结【转载+整合】
- <<C语言深度剖析>>学习笔记之六之内存管理
- Gray-level Co-occurrence Matrix(灰度共生矩阵)
- vc将字符串表示的任意位数字进行小数位保留和四舍五入
- android——CRUD(在上一篇博客的基础上)
- 10种排序算法总结
- KL25用SPI操作nor flash
- jdk和jre有什么区别?
- js定时持行函数
- 希望能得到一些大神的指点,加QQ群:249627436 java技术交流群