“野指针”不是NULL指针,是指向“垃圾”内存的指针。人们一般不会错用NULL指针,因为用if语句很容易判断。但是“野指针”是很危险的,if语句对它不起作用。
“野指针”的成因主要有3种:
(1)指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。例如
char *p = NULL;
char *str = new char(100);
(2)指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针。
指针p被free或delete以后其地址仍然不变(非NULL),只是该地址对应的内存是垃圾,p成了“野指针”。如果此时不把p设置为NULL,会让人误以为p是个合法的指针。
如果程序比较长,我们有时记不住p所指的内存是否已经被释放,在继续使用p之前,通常会用语句if (p != NULL)进行防错处理。很遗憾,此时if语句起不到防错作用,因为即便p不是NULL指针,它也不指向合法的内存块。
(3)指针操作超越了变量的作用范围。这种情况让人防不胜防,示例程序如下:
class A
{
public:
void Func(void){ cout << “Func of class A” << endl; }
};
void Test(void)
{
A *p;
if(...)
{
A a;
p = &a; // 注意 a 的生命期
}
p->Func(); // p是“野指针”
}
函数Test在执行语句p->Func()时,对象a已经消失,而p是指向a的,所以p就成了“野指针”
这就是个最简单的样式,30行都不到:
static void *mem_head = NULL;
void *my_malloc(size_t size)
{
void *p = malloc(size + sizeof(void *));
*(void **)p = mem_head;
mem_head = p;
return p + sizeof(void *);
}
void *my_freeall()
{
void *p;
while(mem_head)
{
mem_head = *(void **)(p = mem_head);
free(p);
}
}
main()
{
char *p = my_malloc(100);
char *q = my_malloc(20);
my_freeall();
}
事实上mem_head应该作为一个与session对应的内存handler,必要的时候可以继续包装一下。这里也没有用chunk优化,调用malloc太多,性能不会很好,反正这些管理代码是可以弄得很短的。
我想要预防野指针,首先应该有良好的编码习惯,比如多用new和delete;class里面有指针数据成员时,在构造函数里面提供new,在析构函数里面用delete;重载=操作符时候删除旧内存,重新分配;删除指向数组的指针,需要delete [] array;当声明一个指针的时候,初始化为NULL;
当你用char * 的时候,建议用string;能用数组的就用数组,最好用STL里面的容器!
等等!!!
这是一个难以控制的问题!!!!特别是大型应用程序中。
函数Test在执行语句p->Func()时,对象a已经消失,而p是指向a的,所以p就成了“野指针”。