C语言动态内存管理
在C语言中,编写程序的时候不能确定内存的大小,希望程序在运行的过程中根据数据量的大小动态的分配内存。动态内存管理,就是指在程序运行过程中动态的申请和释放内存空间。
C语言允许程序动态管理内存,需要时随时开辟,不需要时随时释放。内存的动态管理是通过调用库函数来实现的,主要有malloc和free函数。
一、相关的库函数
1、malloc 函数
函数的原型:
1 | void *malloc(unsigned int size); |
malloc的作用是向系统申请一块大小为size的连续内存空间,如果申请失败,函数返回0,如果申请成功,返回成功分配内存块的起始地址。
例如:
1 | malloc(100); // 申请 100 个字节的临时分配域,返回值为其第一个字节的地址 |
malloc的返回值的地址的基类型为void,即不指向任何类型的数据,只提供一个地址,程序中需要定义一个指针来指向动态分配的内存地址。
例如:
1 | int *pi=malloc(sizeof(int)); |
2、free 函数
函数的原型:
1 | void free(void *p); |
free的作用是释放指针p指向的动态内存空间,p是调用malloc函数时返回的地址,free函数无返回值。
例如:
1 | free(pi); // 释放指针变量pi指向的已分配的动态空间 |
示例(book107.c)
1 | /* |
运行效果
二、内存被耗尽
使用动态分配内存技术的时候,分配出来的内存必须及时释放,否则会引起系统内存耗尽,这话说起来简单,好像很容易做到,但是在实际开发中,程序员往往是漏洞百出。
内存问题是C程序员的主要问题之一,是初学者的恶梦。
三、野指针
野指针就是无效的指针,与空指针不同,野指针无法通过简单地判断是否为 NULL避免,而只能通过养成良好的编程习惯来尽力减少。
1、指针变量未初始化
指针变量刚被创建时不一定会自动初始化成为空指针(与编译器有关),它的缺省值是可能随机的,它会随便乱指。所以,指针变量在创建的同时应当被初始化,要么将指针的值设置为0,要么让它指向合法的内存。
1 | int *pi=0; |
或
1 | int i; |
2、指针释放后之后未置空
指针在free时会把指针所指的内存给释放掉,但指针不一定会赋值0(也与编译器有关),如果对释放后的指针进行操作,相当于非法操作内存。释放内存后应立即将指针置为0。
1 | free(pi); |
四、应用经验
1、数组申明的改进
在C语言的早期标准中,定义数组必须用常量指明大小,不能用变量。
1 | char str[101]; // 可以这样 |
程序在运行的时候,如果要定义一个字符串存放100个字符,那怎么办,只能通过动态分配内存技术。
1 | char *str=malloc(101); |
现在,定义数组可以用变量指明大小,就不必为数组动态分配内存了。
还有,C++的string是一个变长的字符串,非常好用,程序员根本不必关心内存的问题。
2、链表
链表是C语言的一个经典的数据结构,相当于一个动态的结构体数组,非常巧妙,功能强大,但操作也麻烦,在这里我就不介绍了。
在C++中,容器全完代替了链表的功能,极其好用,程序员也不必关心内存的问题。
3、我的建议
在中国,没有纯C程序员,如果他不会C++,不是他对C有多么执着,可能是不会C++。
至少十年了,我不再使用动态内存分配技术,也想不到有什么场景非得用动态内存分配技术。
哦,嵌入式开发可能是个例外,可能还有其它只能用C不能用C++的场景。
动态内存分配并不是什么高大上的技术,我是一个实用的程序员,绝不给自己挖坑,这与水平高低无关。
五、课后作业
编写示例程序,把本章节介绍的知识点全部演示一遍,用程序演示可以加深您的理解和映象。
六、版权声明
C语言技术网原创文章,转载请说明文章的来源、作者和原文的链接。
来源:C语言技术网(www.freecplus.net)
作者:码农有道