0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看威廉希尔官方网站 视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

C语言中的野指针是怎么来的?

Q4MP_gh_c472c21 来源:威廉希尔官方网站 让梦想更伟大 作者:李肖遥 2021-06-01 16:43 次阅读

一、什么是野指针?

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

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

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

二、野指针是怎么来的?

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

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

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

//在win10_64位+vs2017

//来源:威廉希尔官方网站 让梦想更伟大

//作者:李肖遥

#include 《stdio.h》#include 《string.h》

struct Student

{

char* name;

int number;

};

int main()

{

struct Student s;

strcpy(s.name, “Lixiaoyao”); // OOPS!

s.number = 99;

return 0;

}

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

使用已经释放过后的指针

//在win10_64位+vs2017

//来源:威廉希尔官方网站 让梦想更伟大

//作者:李肖遥

#include 《stdio.h》#include 《malloc.h》#include 《string.h》

void func(char* p)

{

printf(“%s

”, p);

free(p);

}

int main()

{

char* s = (char*)malloc(5);

strcpy(s, “Lixiaoyao”);//数组越界

func(s);

printf(“%s

”, s); // OOPS!使用已经释放的指针s

return 0;

}

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

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

//在win10_64位+vs2017

//来源:威廉希尔官方网站 让梦想更伟大

//作者:李肖遥

#include 《stdio.h》

char* func()

{

char p[] = “Lixiaoyao”;

return p;

}

int main()

{

char* s = func();

printf(“%s

”, s); // OOPS!

return 0;

}

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

进行了错误指针运算

//在win10_64位+vs2017

//来源:威廉希尔官方网站 让梦想更伟大

//作者:李肖遥

#include 《stdio.h》

void main()

{

int a[10] = {1,2,3,4,5,6,7,8,9,10};

int *p;

for (int *p = &a[9];p 》= a;){

*--p = 0;

}

}

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

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

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

//在win10_64位+vs2017

//来源:威廉希尔官方网站 让梦想更伟大

//作者:李肖遥

#include 《stdio.h》#include 《string.h》

int main()

{

int a = 1;

int p = &a;

printf(“%d

”,*((int*)p));

/*

在64位下输出错误

32位下输出a的值 1

*/

return 0;

}

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

怎么避免野指针?

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

定义指针时,同时初始化为NULL

在指针解引用之前,先去判断这个指针是不是Null

指针使用完之后,将其赋值为NULL

在指针使用之前,将其赋值绑定给一个可用地址空间

原文标题:详解C语言那些“可怕”的野指针

文章出处:【微信公众号:嵌入式ARM】欢迎添加关注!文章转载请注明出处。

责任编辑:haq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • C语言
    +关注

    关注

    180

    文章

    7604

    浏览量

    136711
  • 指针
    +关注

    关注

    1

    文章

    480

    浏览量

    70553

原文标题:详解C语言那些“可怕”的野指针

文章出处:【微信号:gh_c472c2199c88,微信公众号:嵌入式微处理器】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    C语言中申请的堆内存能不能自动释放

    C语言中申请的堆内存能不能自动释放?每次都要手动 free 太麻烦,也容易忘记。 学过 C++ 的同学,应该首先能想到智能指针。 但是这是C
    的头像 发表于 11-27 09:33 110次阅读

    C语言程序设计教程第4版第8讲:指针

    C语言指针讲解
    发表于 11-20 14:10 0次下载

    C语言指针学习笔记

    本文从底层内存分析,彻底让读者明白C语言指针的本质。
    的头像 发表于 11-05 17:40 230次阅读
    <b class='flag-5'>C</b><b class='flag-5'>语言</b><b class='flag-5'>指针</b>学习笔记

    C语言中的socket编程基础

    Socket编程简介 Socket是一种通信机制,允许程序之间进行通信。在C语言中,socket编程是网络编程的基础。通过使用socket,程序可以发送和接收数据,实现不同计算机之间的通信
    的头像 发表于 11-01 16:51 304次阅读

    C语言指针运算符详解

    C语言中,当你有一个指向数组中某个元素的指针时,你可以对该指针执行某些算术运算,例如加法或减法。这些运算可以用来遍历数组中的元素,如ptr[i]等价于*(ptr + i)。然而,如果
    的头像 发表于 10-30 11:16 243次阅读

    C语言指针详细解析

    可以对数据本身,也可以对存储数据的变量地址进行操作。 指针是一个占据存储空间的实体在这一段空间起始位置的相对距离值。在C/C++语言中指针
    发表于 09-14 10:03

    c语言中从左到右结合怎么看

    C语言中,操作符的结合性(Associativity)是指当操作符在表达式中连续出现时,它们如何与操作数结合的顺序。对于大多数二元操作符(即需要两个操作数的操作符),C语言遵循两种基
    的头像 发表于 08-20 11:42 856次阅读

    面试中的高频问题:指针函数与函数指针,你能完美应对吗?

    一直觉得C语言较其他语言最伟大的地方就是C语言中指针,有些人认为
    的头像 发表于 06-22 08:11 1706次阅读
    面试中的高频问题:<b class='flag-5'>指针</b>函数与函数<b class='flag-5'>指针</b>,你能完美应对吗?

    嵌入式系统中C语言结构体的基础实现与应用

    C语言中的数组只能允许程序员定义存储相同类型数据。但是结构是C语言编程中允许您存储不同数据类型的数据。
    发表于 03-12 14:29 494次阅读
    嵌入式系统中<b class='flag-5'>C</b><b class='flag-5'>语言</b>结构体的基础实现与应用

    C语言中的typedef的应用

    C 语言提供了 typedef 关键字,您可以使用它为类型取一个新的名字。下面的实例为单字节数字定义了一个术语 BYTE。
    发表于 03-06 11:34 381次阅读
    <b class='flag-5'>C</b><b class='flag-5'>语言中</b>的typedef的应用

    C语言指针用法

    C语言编程中善用指针可以简化一些任务的处理,而对于一些任务(比如动态内存分配),必须要有指针才行的。也就是说精通C
    发表于 03-05 14:22 346次阅读
    <b class='flag-5'>C</b><b class='flag-5'>语言</b>的<b class='flag-5'>指针</b>用法

    介绍C语言中错误处理和异常处理的一些常用的方法和策略

    C语言是一种低级的、静态的、结构化的编程语言,它没有提供像C++或Java等高级语言中的异常处理机制,例如try-catch-finally
    的头像 发表于 02-28 14:25 618次阅读

    枚举有多大?c语言枚举end的作用是什么?

    可以是整数或字符,它们被称为枚举常量。枚举常量可以通过枚举成员引用。 枚举的大小是取决于它所表示的范围的大小。在C语言中,枚举没有固定的大小,而是根据其取值范围确定的。如果枚举类型
    的头像 发表于 01-19 14:19 593次阅读

    如何解决C语言中的“访问权限冲突”异常?C语言引发异常原因分析

    一些措施解决和防止其发生。本文将详细介绍C语言中访问权限冲突异常的原因以及解决方法。 一、访问权限冲突异常的原因分析 访问权限冲突异常可分为两类:访问私有成员和访问未定义成员。下面分别分析这两种异常的原因。 1. 访问
    的头像 发表于 01-12 16:03 5647次阅读

    怎么写出效率高、思路清晰的C语言程序?

    要用C语言的思维方式进行程序的构架构建 要有良好的C语言算法基础,以此实现程序的逻辑构架
    的头像 发表于 01-02 14:20 561次阅读