一.悬空指针的导致
#include <stdio.h>
int *create_array() {
int arr[5] = {1, 2, 3, 4, 5}; // 局部数组,在栈上分配
return arr; // 错误!返回局部变量的地址
} // 函数结束,arr 的内存被回收
int main() {
int *dangling_ptr = create_array();
// dangling_ptr 现在是一个悬空指针
printf("%d\n", dangling_ptr[0]); // 未定义行为!可能崩溃或输出乱码
return 0;
}
这是函数创造的临时变量。超过生命周期被销毁。则创造出悬空指针。
#include <stdlib.h>
int main() {
int *ptr = (int *)malloc(sizeof(int) * 10);
// ... 使用 ptr ...
free(ptr); // 内存被释放,ptr 现在指向无效内存(成为悬空指针)
// 错误!ptr 仍然是之前的内存地址,但该内存已不可用
if (ptr != NULL) { // 这个检查是徒劳的,因为 free 不会自动将 ptr 置为 NULL
ptr[0] = 10; // 未定义行为!写入已释放的内存
}
return 0;
}
把创造的指针释放空间后。则为悬空指针。需要重新向数组定为NULL
#include <stdlib.h>
int main() {
int *ptr1 = (int *)malloc(sizeof(int));
int *ptr2 = ptr1; // ptr1 和 ptr2 指向同一块内存
*ptr1 = 5;
free(ptr1); // 释放内存
// ptr1 和 ptr2 现在都是悬空指针!
*ptr2 = 10; // 未定义行为!
return 0;
}
传递指针后,释放内存后。传递无效都为悬空指针。
二.悬空指针的避免
1. 从不返回栈内存的地址
动态分配内存
传递由调用者分配好的缓冲区。
使用全局或静态变量
2.释放后立即置空指针
这是一个极其有效且简单的习惯。在调用 free(ptr)
之后,立刻将 ptr
赋值为 NULL
。
int main() {
int *ptr = (int *)malloc(sizeof(int));
// ... 使用 ptr ...
free(ptr);
ptr = NULL; // 关键步骤!立即置空
// 现在安全了
if (ptr != NULL) { // 条件为假,不会进入
*ptr = 10; // 永远不会执行
}
free(ptr); // free(NULL) 是安全的,什么也不做
return 0;
}
3.注意变量的作用域
确保指针不会在其指向的变量生命周期结束后被使用。