前几天同事小李跑来问我,程序运行着好好的,突然就崩溃了,查了半天没头绪。我一看日志,发现是内存访问越界,再一翻代码,果然是指针操作出了问题。这种情况在C/C++开发里太常见了,尤其是一些老项目或者性能敏感模块,用指针省资源,但一不小心就会踩坑。
指针乱指,内存就遭殃
最常见的问题是使用未初始化的指针。比如你定义了一个指针变量,但没给它赋值,直接拿来读写,那它指向的地址是随机的,轻则程序异常,重则系统都可能卡死。
int *p;
*p = 10; // 危险!p 没有指向合法内存
还有一种情况是用了已经释放的内存。比如你 malloc 了一块内存,用完 free 掉了,但忘了把指针置为 NULL,后面又误以为还能用,结果一操作就崩。
野指针和重复释放是大忌
野指针不是空指针,而是指向已经被释放或未分配内存的指针。这种问题最难查,因为有时候程序还能“碰巧”运行,换个环境或者数据一变,立马出事。
int *p = (int *)malloc(sizeof(int));
free(p);
p = NULL; // 记得清空,避免野指针
还有就是重复释放,同一个指针传进 free 两次,大多数系统会直接报错退出。这种情况多出现在多个函数都试图管理同一块内存时,责任不清。
用工具辅助排查更高效
光靠肉眼看代码很难发现所有问题。建议在调试阶段用 Valgrind 或 AddressSanitizer 这类工具。它们能帮你抓到内存泄漏、越界访问、使用已释放内存等问题。
比如编译时加上 -fsanitize=address,运行时一旦出现非法操作,马上就能定位到具体行号,比打一堆 printf 快多了。
养成好习惯,少背锅
每次 malloc 后立刻检查是否为空,用完立即 free,并把指针设为 NULL。多人协作时,明确谁分配谁释放,别互相甩锅。结构体里如果有指针成员,构造函数初始化成 NULL,析构时判断是否非空再释放。
别觉得这些是小事,线上服务一个内存错误可能导致整个进程挂掉,重启一次损失好几万。早一点发现,少一分风险。