详解C语言那些可怕的野指针

指针是C语言的灵魂,同时也是很容易让人犯错的重难点,用错了指针将是一个灾难。 2021-08-06 13:48:53 C语言野指针内存 一文帮你搞定 90% 的 JS 手写题!面试手写题不慌了 本文可以帮你扩展并巩固自己的JS基础,顺便搞定90%的手写题。在工作中还可以对常用的需求进行手写实现,比如深拷贝、防抖节流等可以直接用于往后的项目中,提高项目开发效率。不说废话了,下面就直接上代码吧。 2021-08-06 13:30:37 JS手写题前端 谷歌宣布:可能创造了突破物理学的“时间水晶” 外媒报道称,谷歌量子计算部门的研究人员发表了一项研究称使用该公司的 Sycamore 量子计算机创建了对抗物理的“时间晶体”。 2021-08-06 13:10:08 谷歌量子计算机 聊聊Go的三色标记法 最近正好在学习 Golang,对它的里面用到的三色标记法的 GC 机制有些好奇(最开始是因为名字让我联想到了三色杯冷饮~),就稍微多深入了解了一下,在这里分享出来,或许将来对你面试啥的有些帮助。

指针是C语言的灵魂,同时也是很容易让人犯错的重难点,用错了指针将是一个灾难。

[[415864]]

一、什么是野指针

指针是C语言的灵魂,同时也是很容易让人犯错的重难点,用错了指针将是一个灾难。

指针变量的本质是值,这个特殊的值是一个内存地址值,而合法的内存地址包括定义的变量的地址(栈)、malloc函数申请堆内存返回的地址(但未使用free释放,是在堆空间动态申请)

需要注意的是,野指针不是NULL指针,通常NULL指针可以使用if语句来判断,但是C语言中没有任何方法用来判断一个指针是否为野指针!

二、野指针是怎么来的?

通常野指针是因为指针变量中保存的值不是一个合法的内存地址或者指向不可用内存的指针而造成的。

而且野指针往往会造成内存越界、段错误等难以找到的问题,下面分几种情况来说说野指针的由来。

局部指针变量没有被初始化

  1. //在win10_64位+vs2017
  2. //来源:技术让梦想更伟大
  3. //作者:李肖遥
  4. #include<stdio.h>
  5. #include<string.h>
  6. structStudent
  7. {
  8. char*name;
  9. intnumber;
  10. };
  11. intmain()
  12. {
  13. structStudents;
  14. strcpy(s.name,"Lixiaoyao");//OOPS!
  15. s.number=99;
  16. return0;
  17. }

局部变量不像全局变量那样,不赋值会自动初始化为0,指针name指向的内存空间地址是随机的,不能向随机地址空间写数据。我们在定义局部指针变量时应该初始化为NULL,局部变量则初始化为0

使用已经释放过后的指针

  1. //在win10_64位+vs2017
  2. //来源:技术让梦想更伟大
  3. //作者:李肖遥
  4. #include<stdio.h>
  5. #include<malloc.h>
  6. #include<string.h>
  7. voidfunc(char*p)
  8. {
  9. printf("%s\n",p);
  10. free(p);
  11. }
  12. intmain()
  13. {
  14. char*s=(char*)malloc(5);
  15. strcpy(s,"Lixiaoyao");//数组越界
  16. func(s);
  17. printf("%s\n",s);//OOPS!使用已经释放的指针s
  18. return0;
  19. }

malloc申请的堆空间释放后,意味着把这片内存归还到空闲链表,其它程序可以使用这片空间,如果其它程序使用了这个空间,可能导致其它程序莫名其妙的被关闭,所以一定要在释放过后将指针变量的值赋值为NULL。

指针所指向的变量在指针之前被销毁

  1. //在win10_64位+vs2017
  2. //来源:技术让梦想更伟大
  3. //作者:李肖遥
  4. #include<stdio.h>
  5. char*func()
  6. {
  7. charp[]="Lixiaoyao";
  8. returnp;
  9. }
  10. intmain()
  11. {
  12. char*s=func();
  13. printf("%s\n",s);//OOPS!
  14. return0;
  15. }

func函数被调用的时候,栈区存放了局部数组p,func返回之后,栈顶指针退出,占用的内存已经被释放掉,此时指针s指向一个被释放掉了栈空间,如果栈空间值被修改了,就不会打印出预期结果,s就变成了一个野指针,所以我们绝对不要在函数中返回局部变量和局部数组的地址。

进行了错误指针运算

  1. //在win10_64位+vs2017
  2. //来源:技术让梦想更伟大
  3. //作者:李肖遥
  4. #include<stdio.h>
  5. voidmain()
  6. {
  7. inta[10]={1,2,3,4,5,6,7,8,9,10};
  8. int*p;
  9. for(int*p=&a[9];p>=a;){
  10. *--p=0;
  11. }
  12. }

程序中在数组第1个元素a[0]被清除之后,指针p的值还继续减下去,而接下去的一次比较运算是用于结束循环的。但表达式p>= a(p >= &a[0])的值是未定义的。

为避免这种情况,一定要确保字符数组要以‘\0’结尾,为防止内存越界,自己编写的内存相关函数需要指定正确的长度信息。

进行了错误的强制类型转换

  1. //在win10_64位+vs2017
  2. //来源:技术让梦想更伟大
  3. //作者:李肖遥
  4. #include<stdio.h>
  5. #include<string.h>
  6. intmain()
  7. {
  8. inta=1;
  9. intp=&a;
  10. printf("%d\n",*((int*)p));
  11. /*
  12. 在64位下输出错误
  13. 32位下输出a的值1
  14. */
  15. return0;
  16. }

上面的程序在64位下输出错误,32位下输出a的值1,在我们写嵌入式程序的时候,会将int类型的一个数据强制转换成一个指针类型用来表示寄存器的地址,这个时候就需要注意了。

怎么避免野指针?

知道了野指针产生的原因,避免方法就出来了,在指针的解引用之前,确保指针指向一个绝对可用的空间。

  1. 定义指针时,同时初始化为NULL
  2. 在指针解引用之前,先去判断这个指针是不是Null
  3. 指针使用完之后,将其赋值为NULL
  4. 在指针使用之前,将其赋值绑定给一个可用地址空间

©本文为清一色官方代发,观点仅代表作者本人,与清一色无关。清一色对文中陈述、观点判断保持中立,不对所包含内容的准确性、可靠性或完整性提供任何明示或暗示的保证。本文不作为投资理财建议,请读者仅作参考,并请自行承担全部责任。文中部分文字/图片/视频/音频等来源于网络,如侵犯到著作权人的权利,请与我们联系(微信/QQ:1074760229)。转载请注明出处:清一色财经

(0)
打赏 微信扫码打赏 微信扫码打赏 支付宝扫码打赏 支付宝扫码打赏
清一色的头像清一色管理团队
上一篇 2023年5月5日 17:58
下一篇 2023年5月5日 17:59

相关推荐

发表评论

登录后才能评论

联系我们

在线咨询:1643011589-QQbutton

手机:13798586780

QQ/微信:1074760229

QQ群:551893940

工作时间:工作日9:00-18:00,节假日休息

关注微信