空指针
C/C++中,用 0 或 NULL 都可以表示空指针。
使用空指针的后果
- 如果对空指针解引用,程序会崩溃。
- 如果对空指针使用delete运算符,系统将忽略该操作,不会出现异常。
为什么空指针访问会出现异常?
NULL 指针分配的分区:其范围是从 0x00000000 到 0x0000FFFF。这段空间是空闲的,对于空闲的空间而言,没有相应的物理存储器与之相对应,所以对这段空间来说,任何读写操作都是会引起异常的。空指针是程序无论在何时都没有物理存储器与之对应的地址。为了保障“无论何时”这个条件,需要人为划分一个空指针的区域,故有上面NULL指针分区。
nullptr
nullptr 在 C++11 引入,使用 nullptr 代替 NULL 可以增加代码的清晰性和可读性。
- nullptr 明确地表示了一个空指针(类型安全),而 NULL 则可能表示一个空指针或一个整数类型的零。在阅读和理解代码时,nullptr 的语义更加明确,可以减少误解和错误。
void func(int); // (1) 接受一个整数的函数
void func(void* ptr); // (2) 接受一个指针的函数
// 尝试使用NULL来调用func函数
func(NULL);
// 编译器将不得不决定是调用(1)版本的func(将NULL解释为整数0)还是调用(2)版本的func(将NULL解释为空指针)。在不同的编译器或不同的编译设置下,这种行为可能是不确定的,有时甚至会导致编译错误。
// 如果我们使用nullptr来调用func函数
func(nullptr);
// 编译器将明确调用(2)版本的func,因为nullptr只能被解释为空指针,与整数类型的参数不兼容。
野指针
野指针是指一个没有被初始化的指针(或者赋值了一个无效的地址)。
野指针的产生通常是因为指针变量声明后未被初始化就直接使用,导致它指向一个未知的内存地址。
使用野指针会导致程序尝试访问一个不合法或不可用的内存区域,可能引发崩溃、数据损坏或者不可预知的行为。
int *ptr; // ptr 未初始化,指向一个随机的内存地址
*ptr = 10; // 使用野指针,可能导致程序崩溃
悬空指针
悬空指针是指一个原本指向有效内存的指针,在该内存被释放或删除后,该指针仍然指向这块内存区域。
悬空指针的产生通常是在使用free、delete等操作释放了指针所指向的内存,但未将指针置空,导致它仍然指向已经释放的内存。
使用悬空指针会导致程序访问已经被释放的内存区域,这块内存可能已经被重新分配给其他对象,导致数据错误、崩溃或其他不可预料的行为。
// 1. 释放后没有置空指针或赋予新的有效地址
int *ptr = (int*)malloc(sizeof(int)); // 分配内存
*ptr = 10;
free(ptr); // 释放内存
*ptr = 20; // 使用悬空指针,可能导致不可预测的行为
// 2. 返回局部变量的指针
int* createInt() {
int x = 10;
return &x; // x 是局部变量,函数结束后 x 被销毁,返回的指针成为悬空指针
// x的内存在函数结束时就不再有效。这样,返回的指针实际上指向了一块已经被释放的内存区域。
}
// 如何避免: 在堆上分配内存
int* createInt() {
int* p = new int(10); // 在堆上分配内存
return p;
}
// 3. 函数参数指针被释放
void foo(int* ptr) {
// 操作 ptr
delete ptr;
}
int main() {
int* ptr = new int;
foo(ptr);
// 在 foo 函数中 ptr 被释放,但在 main 函数中仍然可用,成为悬空指针
// 后续可能会使用 ptr 导致未定义行为
}
// 避免在 foo 中删除传入的指针
// 或者
void foo(int*& ptr) {
// 操作 ptr
delete ptr;
ptr = nullptr; // 将 ptr 置为 nullptr,避免悬空指针
}
// 注意,int*& ptr 表示一个指向 int* 类型的引用。也就是说,ptr 是一个指向 int 类型指针的引用。通过这种方式,函数可以修改调用者传入的指针本身(否则是指针的拷贝),而不仅仅是修改指针指向的值。
// 在 C++ 中,参数传递默认是按值传递的,即使你在函数中修改了指针的值,这些修改也只作用于函数的局部副本,原始指针在函数外部并不会改变。
如何避免
释放内存后将指针置为 nullptr
避免返回局部变量的指针
使用智能指针
注意函数参数的生命周期, 避免在函数内释放调用方传递的指针,或者通过引用传递指针。
1824

被折叠的 条评论
为什么被折叠?



