函数指针- 指针变量中的值非法的内存地址,进而形成野指针
- 野指针不是NULL指针,是指向不可用内存地址的指针
- C语言无法判断一个指针所保存的地址是否合法
野指针的由来
- 局部指针变量==没有初始化==
- 指针所指向的变量==在指针之前被销毁==
- 使用已经释放过的指针
- 进行了错误的指针运算
- 进行了==错误的强制类型转换==
代码示例:
#include <stdio.h>
#include <malloc.h>
int main()
{
int* p1 = (int*)malloc(40);//申请了40个字节
int* p2 = (int*)1234567; //error p2是一个野指针了
int i = 0;
for(i=0; i<40; i++)
{
*(p1 + i) = 40 - i;//error 由于指针运算产生了野指针,改写了非法的内存地址, p1只有40个字节
}
free(p1); //free后,p1里的值还是原来的地址
for(i=0; i<40; i++)
{
p1[i] = p2[i];//error 使用了释放了的指针
}
return 0;
}
==free(p);
p = NULL;==
释放后应该养成将指针赋值为NULL的习惯
杜绝野指针的基本原则
- 绝不返回==局部==变量和==局部==数组的==地址==
- 任何变量定义后必须0初始化(free后给指针赋NULL)
- 字符数组必须确认0结束符后才能成为字符串
任何与内存操作相关的函数必须指定长度信息
- 错误代码示例:
#include <stdio.h>
#include <string.h>
#include <malloc.h>
struct Student
{
char* name;
int number;
};
char* func()
{
char p[] = "D.T.Software";
return p;
}
void del(char* p)
{
printf("%s\n", p);
free(p);
}
int main()
{
struct Student s;//由于没有初始化,产生了野指针
char* p = func();//产生了野指针
strcpy(s.name, p); //使用野指针
s.number = 99;
p = (char*)malloc(5);
strcpy(p, "D.T.Software");//产生内存越界,操作了野指针所指向的内存空间
del(p);
return 0;
}
常见的内存错误
- 结构体成员指针未初始化
- 结构体成员指针为分配足够的内存
- 内存分配成功,但是未初始化
- 内存操作越界
内存操作的规范
- 动态内存申请后,应该检查是否申请成功,检查指针值是否为NULL
- free指针之后必须赋值为NULL
int* p = (int *)malloc(5);
if(p != NULL)
{
//do something
}
free(p);
p = NULL;
- 任何与内存操作相关的函数必须带长度信息
void print(int* p, int size)
{
int i = 0;
char buf[128] = {0};
snprintf(buf,sizeof(buf),"%s","adgadgdg");
for(i = 0; i < size;i++)
{
printf("%d \n",p[i]);
}
}
- malloc操作和free操作必须匹配,防止内存泄漏和多次释放
当malloc次数多于free,产生内存泄漏
当malloc次数少于free,程序可能崩溃
所以malloc和free应该成对出现在同一函数