深入理解指针
1 使用未初始化的指针
指针未初始化时,系统会给指针分配一个随机地址。
int *p = NULL;
*p = 10;
指针p未初始化,故将10写到了未知的内存位置,若p指向系统空间,会导致程序或系统崩溃。
2 没有释放内存
在堆中开辟内存后,使用完成必须释放内存,否则会造成内存泄漏。
int *p = (int *)malloc(100);
free(p);
p = NULL;
3 不断修改指针变量
使用指针开辟了内存空间,然后如果对指针指向进行改变操作,操作完成后直接释放内存,会释放了不该释放的位置;另外程序丢失了对已开辟内存空间的控制,造成内存泄漏。
/* 错误 */
char *p = (char *)malloc(100);
strcpy(p, "abcdefg");
p += 100;
free(p);
p = NULL;
/* 正确 */
char *tmp = p;
tmp += 100;
解决方法是定义两个指向同一内存空间的指针变量,一个用于操作,一个用于释放,避免造成内存泄漏。
4 注意野指针
野指针不是NULL指针,而是指向垃圾内存(系统随机分配的内存地址)的指针。if语句无法判断野指针。野指针的成因主要有三种:
- 声明指针变量时没有初始化。
- 指针变量被free或delete之后,没有置为NULL。
- 操作指针时超过了变量的作用范围。
char *p = (char *)malloc(100);
free(p); //错误,没有置为NULL,成为野指针
5 指针参数申请内存常见错误
若函数的形参是一个指针,则不要用该指针去申请动态内存。
#include <stdlib.h>
void getMem(char *p, int num){
p = (char *)malloc(sizeof(char) * num);
}
int main()
{
char *ptr = NULL;
getMem(ptr, 100);
...
free(ptr);
ptr = NULL;
return 0;
}
错误,调用函数getMem会将ptr的值传递给p,但调用结束后ptr的值并未改变,是一个野指针,且每调用一次getMem函数就会泄漏一块内存。
指针参数申请内存的两种正确用法:
使用函数返回值来传递动态内存:
#include <stdlib.h>
char *getMem(char *p, int num){
p = (char *)malloc(sizeof(char) * num);
return p;
}
int main()
{
char *ptr = NULL;
ptr = getMem(ptr, 100);
...
return 0;
}
使用指向指针的指针作为参数来传递动态内存:在需要改变指针变量本身的时候,需要使用指向指针的指针作为参数,这也是传值与传地址的差别所在。
#include <stdlib.h>
void getMem(char **p, int num){
*p = (char *)malloc(sizeof(char) * num);
}
int main()
{
char *ptr = NULL;
getMem(&ptr, 100);
...
return 0;
}