深入理解C指针学习笔记七之动态内存管理
2016-04-11 22:17
495 查看
只针对额强大很大成都上源于它能追踪动态分配的内存。通过指针来管理这部分内存是很多操作的基础,包括一些用来处理复杂数据结构的操作。要完全利用这些能力,需要理解C的动态内存管理怎么回事。
C程序在运行时环境中执行,这通常是有操作系统提供的环境,支持堆和栈以及其他的程序行为。
注意 C99引入了变长数组,即数组的大小不是在编译时确定而是在运行时确定。不过数组一旦创建出来其长度就不会改变了。
迷途指针是一个常见的问题,我们通过事例说明什么情况下会出现迷途指针并介绍解决迷途指针的方法。指针使用不当可能会早场很多不可预期的效果,可能会产生无效效果,损坏数据或者终止数据。
用malloc类的函数分配内存
用这些内存支持应用程序
用free函数释放内存(释放结束最好将指针置为NULL)
事例程序:
上述程序的内存分配情况:
注意上述使用sizeof(int)指定malloc分配内存的大小可以提高程序的兼容性。因为不同平台上int所占的字节数不同
每次调用malloc,程序结束时必须调用对应的free函数,以防止内存泄露。一般对指针进行释放内存之后将其设置为NULL,防止程序再次对其进行访问出错。
注意给字符串进行分配内存的时候特别注意要多分配一个字节装结束符’\0’(C语言字符串的结尾默认以’\0’结尾).
丢失内存地址
应该调用free函数却没有调用(隐式泄露)
内存泄露的一个重要问题是无法回收内存并重复利用,堆管理器可用的内存将变少,如果内存不断的被分配丢失,那么当需要更多的内存而malloc有不能分配时可能会导致程序终止,极端的情况下会导致操作系统崩溃。
下图说明了两次分配内存的情况,其中500处的内存发生丢失。
每次迭代name会增加1,最后name会指向字符串结尾的NUL,分配的起始地址就丢失了
另一种容易发生内存泄露的情况是struct中含有指向动态分配的内存的指针,那么在释放结构体之前一定要先释放这些指针
C程序在运行时环境中执行,这通常是有操作系统提供的环境,支持堆和栈以及其他的程序行为。
注意 C99引入了变长数组,即数组的大小不是在编译时确定而是在运行时确定。不过数组一旦创建出来其长度就不会改变了。
迷途指针是一个常见的问题,我们通过事例说明什么情况下会出现迷途指针并介绍解决迷途指针的方法。指针使用不当可能会早场很多不可预期的效果,可能会产生无效效果,损坏数据或者终止数据。
动态内存分配
内存分配方法
在C语言中动态内存分配的步骤:用malloc类的函数分配内存
用这些内存支持应用程序
用free函数释放内存(释放结束最好将指针置为NULL)
事例程序:
int *pi = (int*)malloc(sizeof(int)); *pi = 5; printf("pi:%d", *pi); free(pi); pi = NULL;
上述程序的内存分配情况:
注意上述使用sizeof(int)指定malloc分配内存的大小可以提高程序的兼容性。因为不同平台上int所占的字节数不同
每次调用malloc,程序结束时必须调用对应的free函数,以防止内存泄露。一般对指针进行释放内存之后将其设置为NULL,防止程序再次对其进行访问出错。
注意给字符串进行分配内存的时候特别注意要多分配一个字节装结束符’\0’(C语言字符串的结尾默认以’\0’结尾).
//此处pc最多只能装长度为5的字符串 char* pc = (char*)malloc(6); //此处打印的是指针pc在内存中的长度,与malloc多少字节无关,64机器此处结果为8 *pc = "12345"; printf("%zu\n", sizeof(pc)); //此时输出的是字符串的长度,结果为5 printf("%zu\n", strlen(pc));
内存泄露
如果不再使用已经分配的内存却没有将其释放就会发生内存泄露,导致内存泄露的情况有一下两种:丢失内存地址
应该调用free函数却没有调用(隐式泄露)
内存泄露的一个重要问题是无法回收内存并重复利用,堆管理器可用的内存将变少,如果内存不断的被分配丢失,那么当需要更多的内存而malloc有不能分配时可能会导致程序终止,极端的情况下会导致操作系统崩溃。
丢失地址
下面一种情况可以导致内存丢失,即一个指针被连续两次分配内存:
int * pi = (int*)malloc(sizeof(int)); *pi = 5 …… pi = (int*)malloc(sizeof(int));
下图说明了两次分配内存的情况,其中500处的内存发生丢失。
还有另一种情况会发生地址丢失:
char* name = (char*)malloc(strlen("abc") + 1); strcpy(name, "abc"); while(*name != 0) { printf("%c", name); name++; }
每次迭代name会增加1,最后name会指向字符串结尾的NUL,分配的起始地址就丢失了
隐式内存泄露
如果程序在应该释放内存而实际却没有释放,也会发生内存泄露,如果我们不再需要某个对象但仍然保存在堆上,就会发生隐式的内存泄露。这种隐式泄露的带来的主要问题是对象在使用的内存其实不需要了,应该归还给堆,最坏的情况时堆管理器无法按需分配内存,导致程序不得不终止。另一种容易发生内存泄露的情况是struct中含有指向动态分配的内存的指针,那么在释放结构体之前一定要先释放这些指针
相关文章推荐
- 如何组织构建多文件 C 语言程序(二)
- 关于指针的一些事情
- 应用领航:盘点那些年我们一起追过的OS
- 如何写好 C main 函数
- 无奇不有!盘点各国自己开发的操作系统
- Lua和C语言的交互详解
- Lua的内存管理浅析
- 可自定义oem的萝卜家园 Ghost XP 新春装机版 V200801 下载
- C#实现判断操作系统是否为Win8以上版本
- C# Pointer指针应用实例简述
- 关于C语言中参数的传值问题
- 简要对比C语言中三个用于退出进程的函数
- 深入C++中API的问题详解
- 基于C语言string函数的详解
- C语言中fchdir()函数和rewinddir()函数的使用详解
- C语言内存对齐实例详解
- C语言编程中统计输入的行数以及单词个数的方法
- C语言自动生成enum值和名字映射代码
- 使用C语言判断英文字符大小写的方法
- c语言实现的带通配符匹配算法