1 野指针
野指针不是 NULL 指针, 而是指向 “垃圾”内存的指针. 人们通常不会用错 NULL 指针, 因为用 if 条件语句很容易判断; 但是野指针是很危险的, if 语句对它不起作用, 而只能通过养成良好的编程习惯来尽力减少. 对野指针进行操作很容易造成程序错误.
1.1 野指针的成因
- 指针变量没有初始化. 任何指针变量刚被创建时不会自动成为 NULL 指针, 它的默认值是随机的.
- 指针 p 被 free 或者 delete 之后, 没有置为 NULL.
指针操作超越变量作用域. 该情况主要发生在函数调用的过程中.
示例:
void func(int *p)
{
int val = 12;
p = &val; // 当该函数调用结束时, val 的内存被释放
}
int main(int argc, char *argv[])
{
int *p1; // 未初始化
int *p2 = NULL, *p3 = NULL;
int val = 12;
if (p1 != NULL)
*p1 = val; // 使用未初始化的指针, 而引发错误
int *p2 = (int *)malloc(32 * sizeof(int));
if (p2 == NULL)
{
printf("func main err: malloc failed\n");
return -1;
}
func(p3); // 调用函数
if (p3 != NULL)
p2[0] = *p3;
else
return -2;
if (p2 != NULL)
{
delete(p2); // p2 未置为 NULL
}
if (p2 != NULL)
printf("%d", p2[0]); // p2 为野指针, 调用出错
return 0;
}
1.2 避免野指针
步骤:
- 任何指针在创建的时候必须初始化, 不确定指向时初始化为 NULL;
- 任何指针被 free 或 delete 时必须置为 NULL(多级指针时, 应当由内向外逐层 free 或 delete, 最后将主指针置为 NULL );
- 在函数调用时, 严禁返回临时变量的地址, 除非有特殊需求.
2 new/delete
有了 malloc / free , 为什么还要 new / delete 呢? 它们都可用于申请动态内存和释放内存.
2.1 主要区别
对于非内部数据类型的对象而言, 只是使用 malloc / free 已经无法满足动态对象的要求. 主要区别如下:
- malloc 和 free 是 C/C++ 的标准库函数, new 和 delete 是 C++ 的运算符.
- malloc 无法自动指向构造函数, free 无法自动执行析构函数, 而 new 和 delete 可以自动完成相应的工作.
又因为 C++ 对象的复杂性(继承, 派生), 使得在进行初始化对象和析构对象的过程中的任务量剧增, 这两个问题会消耗大量的时间, 因此急需能够自动为我们完成上述两项工作的函数或操作符, 在此情况下 new / delete的出现就成为了必然.