C语言 NULL指针 动态内存分配释放 野指针
执行结果截图:
如果if语句判断指针p3是NULL,则会输出:
代码:
#include <stddef.h>
#include <stdio.h>
#include <malloc.h>
#include <string.h>
int main()
{
//整型指针未被初始化,是个野指针
int * p1;
int num = 1024;
int * p2 = #
int * p3 = NULL;
// 野指针p1访问的是垃圾内存地址,因此对p1是否为NULL进行判断时,不要对p1用 * 解引用
// 对野指针解引用会得到错误的值,并且程序很可能不报错
// 先判断指针是否初始化为NULL,如果没有就提示
printf("p1:%p\n&p1:%p\nnum:%d\np2:%p\np3:NULL\n", p1, &p1, num, p2);
if (NULL != p1){
printf("Warning:指针p1指向的地址值不是NULL,解引用前请留意是否是野指针!\n");
}
else {
printf("Warning:指针p1指向的地址值已经初始化为NULL,不能被解引用!\n");
}
// 给整型指针p1指向的地址值分配动态内存空间
// 用sizeof(int)是为了确保跨平台,分配适合该平台的int类型空间
p1 = malloc(sizeof(int));
printf("指针p1的值发生变化,已被分配动态内存空间\n判断指针p1是否指向NULL...\n");
// 判断指针p1是否已被正确的分配了空间
if (NULL == p1) {
printf("指针指向的地址值是NULL, malloc error动态内存分配错误!\n");
//跳出整个程序
exit(1);
}
else{
printf("指针p1指向的动态内存空间尚未被初始化,* p1读取的是垃圾数据\np1:%p\n* p1:%d\n&p1:%p\n", p1, * p1, &p1);
//将指针p1所在的动态内存空间都初始化为0
memset(p1,0,sizeof(int));
printf("指针p1指向的动态内存空间已被初始化!* p1被赋值0\np1:%p\n* p1:%d\n&p1:%p\n", p1, * p1, &p1);
* p1 = num;
printf("执行* p1 = num\np1:%p\n* p1:%d\n&p1:%p\n", p1, * p1, &p1);
free(p1);
printf("指针p1指向的动态内存空间已释放!\np1:%p\n* p1:%d\n&p1:%p\n", p1, * p1, &p1);
//把p1初始化为NULL
if (NULL != p1) {
p1 = NULL;
printf("指针p1指向的地址值不是NULL,现在初始化为NULL,请不要对NULL值用 * 解引用!\np1:%p\n&p1:%p\n", p1, &p1);
}
else {
printf("Warning:指针p1指向的地址值已经初始化为NULL,不能被解引用!\n");
}
}
// p1被初始化为NULL后,语句中一用到p1就会报错。
// 如果释放内存后指针p1没有NULL,那么很可能就会忘记初始化从而造成野指针
// 这个报错有利于提醒编程者把p1指向一个有效的正确的地址而不是成为野指针
printf("执行p1 = p2\np1:%p\n", p1 = p2);
if (NULL != p2){
printf("Warning:指针p2指向的地址值不是NULL,解引用前请留意是否是野指针!\n");
printf("p2:%p\n* p2:%d\n&p2:%p\n", p2, * p2, &p2);
} else {
printf("Warning:指针p2指向的地址值已经初始化为NULL,不能被解引用!\np2:%p\n&p2:%p\n", p2, &p2);
}
// 如果在含p3 = p1的语句前面加双斜杠注释符(也就是不执行p3 = p1)
// 那么后面执行if(NULL != p3)判断的结果是另一个对p3的提示
// printf("执行p3 = p1\np3:%p\n", p3 = p1);
if (NULL != p3)
{
printf("Warning:指针p3指向的地址值不是NULL,解引用前请留意是否是野指针!\n");
printf("p3:%p\n* p3:%d\n&p3:%p\n", p3, * p3, &p3);
} else
{
printf("Warning:p3指向的地址值已经初始化为NULL,不能被解引用!\np3:%p\n&p3:%p\n", p3, &p3);
}
/* 当在不知道指针初始化为什么地址的时候,将它初始化为NULL,
* 在对指针进行解引用时,先判断是否为NULL,
* 例如int * p = NULL;
* ...经过分配动态内存和一些运算...特别是用free或delete释放了内存之后
* 用if(NULL != p)对野指针进行判断,并及时把野指针p初始化为NULL
* 通过把指针初始化为NULL和检查是否NULL,可以一定程度上防止野指针造成危害
*
* 当指针为NULL时,对指针解引用会报错的原因:
* NULL指针分配的分区:其范围是从 0x00000000到0x0000FFFF。
* 这段空间是空闲的,对于空闲的空间而言,没有相应的物理存储器与之相对应,
* 所以对这段空间来说,任何读写操作都会引起异常。
*
* 野指针的的成因:
* 1、指针变量没有被初始化。默认值是随机的,它会乱指一气。
* 2、指针p被free或者delete之后,指针成为野指针,没有置为NULL,让人误以为p是个合法的指针。
* 3、指针操作超越了变量的作用范围。这种情况让人防不胜防。
*/
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】