参考书籍《深入理解c指针》原书作者:RichardReese华盛顿州塔尔顿州立大学副教授
篇首语
指针为什么强大?
因为能够追踪动态分配的内存,通过指针来管理这部分内存是很多操作的基础
由于可以先分配内存然后释放,因而应用程序可以更灵活高效的管理内存,不必为了适应数据结构可能的
最大长度而分配内存,只要分配实际需要的内存即可
一、动态内存分配
(一)、在c中动态分配内存的基本步骤
(1)用malloc 类的函数分配内存
(2)用这些内存支持应用程序
(3)用free函数释放内存(个人认为代码安全性,释放之后最好置为NULL)
int *pi = (int*)malloc(sizeof(int));
*pi = 5;
printf("*pi = %d\n",*pi);
free(pi);
注意下写法:
Demo1
int *pi;
*pi = (int*)malloc(sizeof(int)); // 内存地址赋值给变量值,不对
Demo2
pi = (int*)malloc(sizeof(int)); // 正确,地址指向内存
注意内存访问越界的问题,错误示例
char *pc = (char*)malloc(6);
for(int i = 0;i<8;i++)
{
*pi[i] = 0;
}
(二)、内存泄漏
如果不再使用已经分配的内存却没有将其释放,就会发生内存泄漏
引发这种状况的原因如下:
(1)、丢失内存地址
(2)、应该调用free函数却没有调用
(3)、while循环申请内存
char* chunk;
while(1)
{
chunk = (char*)malloc(10000);
printf("Allocating\n");
}
1、丢失地址
(1)、pi指针先后指向两块内存
int *pi = (int*) malloc(sizeof(int));
*pi = 5;
pi = (int*)malloc(sizeof(int));
这样一来,第一块内存就没有被释放
(2)、直至遍历到字符串结尾
char *name = (char*)malloc(strlen("Susan")+1);
strcpy(name,"Susan");
while(NULL!=*name)
{
printf("%c",*name);
name++;
}
2、隐式内存泄漏
没有用free释放
二、动态内存分配函数
malloc 从堆上分配内存
realloc 在之前分配的内存块的基础上,将内存重新分配为更大或者更小的部分
calloc 从堆上分配内存并清零
free 奖励
三、用free函数释放内存
1、指针在释放之后仍然可能有值,这样的指针称之为迷途指针
2、如果free的指针所指向的内存不是由于malloc分配的,那么用free释放不合法
如果free的指针所指向的内存不是由于malloc分配的,那么用free释放不合法
int num;
int pi = #
free(pi); // 未定义行为
3、将指针释放后置为NULL,防止产生迷途指针,什么是迷途指针呢?不为NULL的指针,
也不是指向常量的指针,而是指向“垃圾”内存的指针
4、重复释放同一块内存,程序会异常
int p1 = (int*)malloc(sizeof(int));
int* p2 = p1;
free(p1);
free(p2);
5、堆和系统内存
6、程序结束前释放内存
四、迷途指针
一、几个示例
1、内存释放后,继续向这个位置写入数据,这样做的结果是不可预期的
int *pi = (int *)malloc(sizeof(int));
free(pi);
*pi = 10;
2、多个指针指向同一块内存区域,然后通过一个指针释放那块内存区域
int *p1 = (int *)malloc(sizeof(int));
int p2 = p1;
free(p1);
3、使用块语句的时候,可能会出现一些问题
int pi
{
int tmp = 5;
pi = &tmp;
}
// 这里pi变成迷途指针
二、处理迷途指针
1、释放指针后置为NULL(最为常见)
2、写一个特殊函数代替free函数
3、用第三方工具检测迷途指针或者其他问题