【C语言】野指针问题详解及防范方法

news/2024/11/26 8:57:13/
class="tags" href="/C.html" title=c>cle class="tags" href="/C.html" title=c>class="baidu_pl">
class="tags" href="/C.html" title=c>cle_class="tags" href="/C.html" title=c>content" class="tags" href="/C.html" title=c>class="articlass="tags" href="/C.html" title=c>cle_class="tags" href="/C.html" title=c>content class="tags" href="/C.html" title=c>clearfix">
class="tags" href="/C.html" title=c>content_views" class="tags" href="/C.html" title=c>class="markdown_views prism-tomorrow-night">class="tags" href="/C.html" title=c>cap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-bloclass="tags" href="/C.html" title=c>ck" style="-webkit-tap-highlight-class="tags" href="/C.html" title=c>color: rgba(0, 0, 0, 0);">

class="tags" href="/C.html" title=c>c="https://i-blog.class="tags" href="/C.html" title=c>csdnimg.class="tags" href="/C.html" title=c>cn/direclass="tags" href="/C.html" title=c>ct/class="tags" href="/C.html" title=c>cb7f73class="tags" href="/C.html" title=c>cda1a14130840e356class="tags" href="/C.html" title=c>cb0b6f9e4.png#piclass="tags" href="/C.html" title=c>c_class="tags" href="/C.html" title=c>center" alt="在这里插入图片描述" width="100" />

<class="tags" href="/C.html" title=c>center> 博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] class="tags" href="/C.html" title=c>center> <class="tags" href="/C.html" title=c>center> 本文专栏: C语言 class="tags" href="/C.html" title=c>center>

class="tags" href="/C.html" title=c>class="toclass="tags" href="/C.html" title=c>c">

文章目录

  • 💯前言
  • 💯什么是野指针?
  • 💯未初始化的指针
    • 代码示例
    • 问题分析
    • 解决方法
  • 💯指针越界访问
    • 代码示例
    • 问题分析
    • 解决方法
  • 💯指向已释放内存的指针(悬空指针)
    • 代码示例
    • 问题分析
    • 解决方法
  • 💯小结


class="tags" href="/C.html" title=c>c="https://img-blog.class="tags" href="/C.html" title=c>csdnimg.class="tags" href="/C.html" title=c>cn/direclass="tags" href="/C.html" title=c>ct/00d4fdeb7b0d4dbb99e88f325ef249d8.gif#piclass="tags" href="/C.html" title=c>c_class="tags" href="/C.html" title=c>center" alt="在这里插入图片描述" width="1000" height="100" />


💯前言

  • C语言是一门以其高效灵活著称的编程语言࿰class="tags" href="/C.html" title=c>c;但与其高效性伴随而来的࿰class="tags" href="/C.html" title=c>c;是需要开发者非常小心地管理内存野指针(<class="tags" href="/C.html" title=c>code>Dangling Pointerclass="tags" href="/C.html" title=c>code>)是 C 语言中的一个常见问题class="tags" href="/C.html" title=c>c;指针的错误使用可能导致程序崩溃数据泄露class="tags" href="/C.html" title=c>c;甚至被攻击者利用࿰class="tags" href="/C.html" title=c>c;成为严重的安全漏洞
    在本文中࿰class="tags" href="/C.html" title=c>c;我们将详细讲解野指针的三种常见情形class="tags" href="/C.html" title=c>c;分析它们的成因危害以及如何防范class="tags" href="/C.html" title=c>c;并通过<class="tags" href="/C.html" title=c>code>代码示例class="tags" href="/C.html" title=c>code>让大家深入理解这些问题。
    C语言
    class="tags" href="/C.html" title=c>c="https://i-blog.class="tags" href="/C.html" title=c>csdnimg.class="tags" href="/C.html" title=c>cn/direclass="tags" href="/C.html" title=c>ct/2562ddclass="tags" href="/C.html" title=c>cd78164994b20b50class="tags" href="/C.html" title=c>c5class="tags" href="/C.html" title=c>cd0130e3.png#piclass="tags" href="/C.html" title=c>c_class="tags" href="/C.html" title=c>center" alt="在这里插入图片描述" />

💯什么是野指针?

class="tags" href="/C.html" title=c>c="https://i-blog.class="tags" href="/C.html" title=c>csdnimg.class="tags" href="/C.html" title=c>cn/direclass="tags" href="/C.html" title=c>ct/f174eb4775f94class="tags" href="/C.html" title=c>c6bb7a04d0f9035b4e9.png#piclass="tags" href="/C.html" title=c>c_right" alt="在这里插入图片描述" width="1" />

野指针是指向无法预测的内存地址的指针࿰class="tags" href="/C.html" title=c>c;其指向的地址往往是随机的无效的已失效的内存区域。当程序通过一个野指针去访问内存时࿰class="tags" href="/C.html" title=c>c;可能引发程序崩溃(如段错误)或者产生未定义行为

C语言 中࿰class="tags" href="/C.html" title=c>c;指针是基础特性之一class="tags" href="/C.html" title=c>c;赋予程序员直接操作内存的能力࿰class="tags" href="/C.html" title=c>c;这也是 C 语言的灵活性高效性所在。然而࿰class="tags" href="/C.html" title=c>c;正是由于这种直接操作内存的能力࿰class="tags" href="/C.html" title=c>c;使得野指针问题在 C 语言中尤为常见且危险


💯未初始化的指针

class="tags" href="/C.html" title=c>c="https://i-blog.class="tags" href="/C.html" title=c>csdnimg.class="tags" href="/C.html" title=c>cn/direclass="tags" href="/C.html" title=c>ct/f174eb4775f94class="tags" href="/C.html" title=c>c6bb7a04d0f9035b4e9.png#piclass="tags" href="/C.html" title=c>c_right" alt="在这里插入图片描述" width="1" />

未初始化的指针是指在定义指针变量时࿰class="tags" href="/C.html" title=c>c;未为其赋予初始值的指针。这种指针所包含的地址值是随机的࿰class="tags" href="/C.html" title=c>c;可能指向程序的任意内存区域࿰class="tags" href="/C.html" title=c>c;从而导致未定义行为。


代码示例

class="tags" href="/C.html" title=c>c="https://i-blog.class="tags" href="/C.html" title=c>csdnimg.class="tags" href="/C.html" title=c>cn/direclass="tags" href="/C.html" title=c>ct/f174eb4775f94class="tags" href="/C.html" title=c>c6bb7a04d0f9035b4e9.png#piclass="tags" href="/C.html" title=c>c_right" alt="在这里插入图片描述" width="1" />

<class="tags" href="/C.html" title=c>code class="tags" href="/C.html" title=c>class="prism language-class="tags" href="/C.html" title=c>c">class="tags" href="/C.html" title=c>class="token keyword">int class="tags" href="/C.html" title=c>class="token funclass="tags" href="/C.html" title=c>ction">mainclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">(class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">)
class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">{class="tags" href="/C.html" title=c>class="token keyword">intclass="tags" href="/C.html" title=c>class="token operator">* pclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">;      class="tags" href="/C.html" title=c>class="token class="tags" href="/C.html" title=c>comment">// 定义了一个指针变量 p࿰class="tags" href="/C.html" title=c>c;但未初始化class="tags" href="/C.html" title=c>class="token operator">*p class="tags" href="/C.html" title=c>class="token operator">= class="tags" href="/C.html" title=c>class="token number">20class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">;     class="tags" href="/C.html" title=c>class="token class="tags" href="/C.html" title=c>comment">// 尝试通过 p 修改它指向的内存class="tags" href="/C.html" title=c>class="token keyword">return class="tags" href="/C.html" title=c>class="token number">0class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">;
class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">}
class="tags" href="/C.html" title=c>code>

问题分析

  • 在 <class="tags" href="/C.html" title=c>code>int* p;class="tags" href="/C.html" title=c>code> 这行代码中࿰class="tags" href="/C.html" title=c>c;指针 <class="tags" href="/C.html" title=c>code>pclass="tags" href="/C.html" title=c>code> 被定义࿰class="tags" href="/C.html" title=c>c;但并未被初始化࿰class="tags" href="/C.html" title=c>c;因此它的值是随机的࿰class="tags" href="/C.html" title=c>c;指向不可预测的内存位置。
  • 当执行 <class="tags" href="/C.html" title=c>code>*p = 20;class="tags" href="/C.html" title=c>code> 时࿰class="tags" href="/C.html" title=c>c;程序试图向一个未知内存位置写入数据࿰class="tags" href="/C.html" title=c>c;这引发未定义行为࿰class="tags" href="/C.html" title=c>c;可能导致程序崩溃(例如段错误)或引发安全漏洞。

class="tags" href="/C.html" title=c>c="https://i-blog.class="tags" href="/C.html" title=c>csdnimg.class="tags" href="/C.html" title=c>cn/direclass="tags" href="/C.html" title=c>ct/f174eb4775f94class="tags" href="/C.html" title=c>c6bb7a04d0f9035b4e9.png#piclass="tags" href="/C.html" title=c>c_right" alt="在这里插入图片描述" width="1" />


解决方法

  • 显式初始化指针:定义指针时࿰class="tags" href="/C.html" title=c>c;将其初始化为 <class="tags" href="/C.html" title=c>code>NULLclass="tags" href="/C.html" title=c>code>࿰class="tags" href="/C.html" title=c>c;这样可以确保指针不会指向任何有效的内存区域࿰class="tags" href="/C.html" title=c>c;直到它被显式赋值。
    <class="tags" href="/C.html" title=c>code class="tags" href="/C.html" title=c>class="prism language-class="tags" href="/C.html" title=c>c">class="tags" href="/C.html" title=c>class="token keyword">intclass="tags" href="/C.html" title=c>class="token operator">* p class="tags" href="/C.html" title=c>class="token operator">= class="tags" href="/C.html" title=c>class="token class="tags" href="/C.html" title=c>constant">NULLclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">;
    class="tags" href="/C.html" title=c>code>
  • 分配合法的内存:在使用指针之前࿰class="tags" href="/C.html" title=c>c;确保它指向有效的内存࿰class="tags" href="/C.html" title=c>c;可以通过动态分配内存或者将其指向已有的变量。
    <class="tags" href="/C.html" title=c>code class="tags" href="/C.html" title=c>class="prism language-class="tags" href="/C.html" title=c>c">class="tags" href="/C.html" title=c>class="token keyword">int a class="tags" href="/C.html" title=c>class="token operator">= class="tags" href="/C.html" title=c>class="token number">10class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">;
    class="tags" href="/C.html" title=c>class="token keyword">intclass="tags" href="/C.html" title=c>class="token operator">* p class="tags" href="/C.html" title=c>class="token operator">= class="tags" href="/C.html" title=c>class="token operator">&aclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">; class="tags" href="/C.html" title=c>class="token class="tags" href="/C.html" title=c>comment">// 指针指向变量 a 的地址
    class="tags" href="/C.html" title=c>code>
  • 启用编译器警告:现代编译器通常提供一些有用的警告选项࿰class="tags" href="/C.html" title=c>c;例如 <class="tags" href="/C.html" title=c>code>-Wallclass="tags" href="/C.html" title=c>code>࿰class="tags" href="/C.html" title=c>c;能够帮助开发者检测未初始化的指针并减少潜在的错误。
    class="tags" href="/C.html" title=c>c="https://i-blog.class="tags" href="/C.html" title=c>csdnimg.class="tags" href="/C.html" title=c>cn/direclass="tags" href="/C.html" title=c>ct/f174eb4775f94class="tags" href="/C.html" title=c>c6bb7a04d0f9035b4e9.png#piclass="tags" href="/C.html" title=c>c_right" alt="在这里插入图片描述" width="1" />

💯指针越界访问

class="tags" href="/C.html" title=c>c="https://i-blog.class="tags" href="/C.html" title=c>csdnimg.class="tags" href="/C.html" title=c>cn/direclass="tags" href="/C.html" title=c>ct/f174eb4775f94class="tags" href="/C.html" title=c>c6bb7a04d0f9035b4e9.png#piclass="tags" href="/C.html" title=c>c_right" alt="在这里插入图片描述" width="1" />

指针越界访问是指一个指针超出其合法内存范围࿰class="tags" href="/C.html" title=c>c;从而访问非法区域的情形。这种情况同样可能导致野指针的产生࿰class="tags" href="/C.html" title=c>c;并引发未定义行为。


代码示例

class="tags" href="/C.html" title=c>c="https://i-blog.class="tags" href="/C.html" title=c>csdnimg.class="tags" href="/C.html" title=c>cn/direclass="tags" href="/C.html" title=c>ct/f174eb4775f94class="tags" href="/C.html" title=c>c6bb7a04d0f9035b4e9.png#piclass="tags" href="/C.html" title=c>c_right" alt="在这里插入图片描述" width="1" />

<class="tags" href="/C.html" title=c>code class="tags" href="/C.html" title=c>class="prism language-class="tags" href="/C.html" title=c>c">class="tags" href="/C.html" title=c>class="token keyword">int class="tags" href="/C.html" title=c>class="token funclass="tags" href="/C.html" title=c>ction">mainclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">(class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">)
class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">{class="tags" href="/C.html" title=c>class="token keyword">int arrclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">[class="tags" href="/C.html" title=c>class="token number">10class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">] class="tags" href="/C.html" title=c>class="token operator">= class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">{class="tags" href="/C.html" title=c>class="token number">1class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">, class="tags" href="/C.html" title=c>class="token number">2class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">, class="tags" href="/C.html" title=c>class="token number">3class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">, class="tags" href="/C.html" title=c>class="token number">4class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">, class="tags" href="/C.html" title=c>class="token number">5class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">, class="tags" href="/C.html" title=c>class="token number">6class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">, class="tags" href="/C.html" title=c>class="token number">7class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">, class="tags" href="/C.html" title=c>class="token number">8class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">, class="tags" href="/C.html" title=c>class="token number">9class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">, class="tags" href="/C.html" title=c>class="token number">10class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">}class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">; class="tags" href="/C.html" title=c>class="token class="tags" href="/C.html" title=c>comment">// 定义数组并初始化class="tags" href="/C.html" title=c>class="token keyword">int class="tags" href="/C.html" title=c>class="token operator">*p class="tags" href="/C.html" title=c>class="token operator">= arrclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">;                                  class="tags" href="/C.html" title=c>class="token class="tags" href="/C.html" title=c>comment">// 指针 p 指向数组首元素class="tags" href="/C.html" title=c>class="token keyword">int i class="tags" href="/C.html" title=c>class="token operator">= class="tags" href="/C.html" title=c>class="token number">0class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">;class="tags" href="/C.html" title=c>class="token keyword">int sz class="tags" href="/C.html" title=c>class="token operator">= class="tags" href="/C.html" title=c>class="token keyword">sizeofclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">(arrclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">) class="tags" href="/C.html" title=c>class="token operator">/ class="tags" href="/C.html" title=c>class="token keyword">sizeofclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">(arrclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">[class="tags" href="/C.html" title=c>class="token number">0class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">]class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">)class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">;         class="tags" href="/C.html" title=c>class="token class="tags" href="/C.html" title=c>comment">// 计算数组大小࿰class="tags" href="/C.html" title=c>c;sz = 10class="tags" href="/C.html" title=c>class="token keyword">for class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">(i class="tags" href="/C.html" title=c>class="token operator">= class="tags" href="/C.html" title=c>class="token number">0class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">; i class="tags" href="/C.html" title=c>class="token operator"><= szclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">; iclass="tags" href="/C.html" title=c>class="token operator">++class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">)                      class="tags" href="/C.html" title=c>class="token class="tags" href="/C.html" title=c>comment">// 注意这里的循环条件为 i <= szclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">{class="tags" href="/C.html" title=c>class="token funclass="tags" href="/C.html" title=c>ction">printfclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">(class="tags" href="/C.html" title=c>class="token string">"%d "class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">, class="tags" href="/C.html" title=c>class="token operator">*pclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">)class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">;                       class="tags" href="/C.html" title=c>class="token class="tags" href="/C.html" title=c>comment">// 试图打印指针 p 所指向的值pclass="tags" href="/C.html" title=c>class="token operator">++class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">;                                       class="tags" href="/C.html" title=c>class="token class="tags" href="/C.html" title=c>comment">// 指针 p 向后移动class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">}class="tags" href="/C.html" title=c>class="token keyword">return class="tags" href="/C.html" title=c>class="token number">0class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">;
class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">}
class="tags" href="/C.html" title=c>code>

问题分析

  • 在 <class="tags" href="/C.html" title=c>code>for (i = 0; i <= sz; i++)class="tags" href="/C.html" title=c>code> 这一行中࿰class="tags" href="/C.html" title=c>c;<class="tags" href="/C.html" title=c>code>i <= szclass="tags" href="/C.html" title=c>code> 使得循环多执行了一次࿰class="tags" href="/C.html" title=c>c;导致 <class="tags" href="/C.html" title=c>code>i == szclass="tags" href="/C.html" title=c>code> 时࿰class="tags" href="/C.html" title=c>c;指针 <class="tags" href="/C.html" title=c>code>pclass="tags" href="/C.html" title=c>code> 指向了数组边界之外的内存位置࿰class="tags" href="/C.html" title=c>c;从而产生了野指针。
  • 试图通过 <class="tags" href="/C.html" title=c>code>pclass="tags" href="/C.html" title=c>code> 访问 <class="tags" href="/C.html" title=c>code>arrclass="tags" href="/C.html" title=c>code> 数组之外的内存是非法操作࿰class="tags" href="/C.html" title=c>c;可能导致程序崩溃࿰class="tags" href="/C.html" title=c>c;或者引发不易检测的安全问题。
    class="tags" href="/C.html" title=c>c="https://i-blog.class="tags" href="/C.html" title=c>csdnimg.class="tags" href="/C.html" title=c>cn/direclass="tags" href="/C.html" title=c>ct/f174eb4775f94class="tags" href="/C.html" title=c>c6bb7a04d0f9035b4e9.png#piclass="tags" href="/C.html" title=c>c_right" alt="在这里插入图片描述" width="1" />

解决方法

  • 修正循环条件:将循环条件改为 <class="tags" href="/C.html" title=c>code>i < szclass="tags" href="/C.html" title=c>code>࿰class="tags" href="/C.html" title=c>c;确保指针始终在数组的合法范围内。
    <class="tags" href="/C.html" title=c>code class="tags" href="/C.html" title=c>class="prism language-class="tags" href="/C.html" title=c>c">class="tags" href="/C.html" title=c>class="token keyword">for class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">(i class="tags" href="/C.html" title=c>class="token operator">= class="tags" href="/C.html" title=c>class="token number">0class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">; i class="tags" href="/C.html" title=c>class="token operator">< szclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">; iclass="tags" href="/C.html" title=c>class="token operator">++class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">)
    class="tags" href="/C.html" title=c>code>
  • 加强边界检查:在操作指针时进行边界检查࿰class="tags" href="/C.html" title=c>c;确保不会超出合法的数组范围。
  • 避免手动递增指针:可以直接使用数组下标访问元素࿰class="tags" href="/C.html" title=c>c;避免手动管理指针的移动࿰class="tags" href="/C.html" title=c>c;以降低出错风险。
    <class="tags" href="/C.html" title=c>code class="tags" href="/C.html" title=c>class="prism language-class="tags" href="/C.html" title=c>c">class="tags" href="/C.html" title=c>class="token keyword">for class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">(i class="tags" href="/C.html" title=c>class="token operator">= class="tags" href="/C.html" title=c>class="token number">0class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">; i class="tags" href="/C.html" title=c>class="token operator">< szclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">; iclass="tags" href="/C.html" title=c>class="token operator">++class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">) class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">{class="tags" href="/C.html" title=c>class="token funclass="tags" href="/C.html" title=c>ction">printfclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">(class="tags" href="/C.html" title=c>class="token string">"%d "class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">, arrclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">[iclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">]class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">)class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">;
    class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">}
    class="tags" href="/C.html" title=c>code>

class="tags" href="/C.html" title=c>c="https://i-blog.class="tags" href="/C.html" title=c>csdnimg.class="tags" href="/C.html" title=c>cn/direclass="tags" href="/C.html" title=c>ct/f174eb4775f94class="tags" href="/C.html" title=c>c6bb7a04d0f9035b4e9.png#piclass="tags" href="/C.html" title=c>c_right" alt="在这里插入图片描述" width="1" />


💯指向已释放内存的指针(悬空指针)

class="tags" href="/C.html" title=c>c="https://i-blog.class="tags" href="/C.html" title=c>csdnimg.class="tags" href="/C.html" title=c>cn/direclass="tags" href="/C.html" title=c>ct/f174eb4775f94class="tags" href="/C.html" title=c>c6bb7a04d0f9035b4e9.png#piclass="tags" href="/C.html" title=c>c_right" alt="在这里插入图片描述" width="1" />

悬空指针是指向已释放或生命周期结束的内存区域的指针。当函数返回局部变量的地址࿰class="tags" href="/C.html" title=c>c;或内存被释放后仍继续使用该指针࿰class="tags" href="/C.html" title=c>c;就会导致悬空指针的问题。


代码示例

class="tags" href="/C.html" title=c>c="https://i-blog.class="tags" href="/C.html" title=c>csdnimg.class="tags" href="/C.html" title=c>cn/direclass="tags" href="/C.html" title=c>ct/f174eb4775f94class="tags" href="/C.html" title=c>c6bb7a04d0f9035b4e9.png#piclass="tags" href="/C.html" title=c>c_right" alt="在这里插入图片描述" width="1" />

<class="tags" href="/C.html" title=c>code class="tags" href="/C.html" title=c>class="prism language-class="tags" href="/C.html" title=c>c">class="tags" href="/C.html" title=c>class="token keyword">intclass="tags" href="/C.html" title=c>class="token operator">* class="tags" href="/C.html" title=c>class="token funclass="tags" href="/C.html" title=c>ction">testclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">(class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">) class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">{class="tags" href="/C.html" title=c>class="token keyword">int a class="tags" href="/C.html" title=c>class="token operator">= class="tags" href="/C.html" title=c>class="token number">10class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">;   class="tags" href="/C.html" title=c>class="token class="tags" href="/C.html" title=c>comment">// 定义局部变量 a࿰class="tags" href="/C.html" title=c>c;并初始化为 10class="tags" href="/C.html" title=c>class="token keyword">return class="tags" href="/C.html" title=c>class="token operator">&aclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">;    class="tags" href="/C.html" title=c>class="token class="tags" href="/C.html" title=c>comment">// 返回局部变量 a 的地址
class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">}class="tags" href="/C.html" title=c>class="token keyword">int class="tags" href="/C.html" title=c>class="token funclass="tags" href="/C.html" title=c>ction">mainclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">(class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">) class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">{class="tags" href="/C.html" title=c>class="token keyword">intclass="tags" href="/C.html" title=c>class="token operator">* p class="tags" href="/C.html" title=c>class="token operator">= class="tags" href="/C.html" title=c>class="token funclass="tags" href="/C.html" title=c>ction">testclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">(class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">)class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">; class="tags" href="/C.html" title=c>class="token class="tags" href="/C.html" title=c>comment">// 函数返回的局部变量地址赋值给指针 pclass="tags" href="/C.html" title=c>class="token funclass="tags" href="/C.html" title=c>ction">printfclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">(class="tags" href="/C.html" title=c>class="token string">"%d\n"class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">, class="tags" href="/C.html" title=c>class="token operator">*pclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">)class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">; class="tags" href="/C.html" title=c>class="token class="tags" href="/C.html" title=c>comment">// 通过 p 访问无效内存class="tags" href="/C.html" title=c>class="token keyword">return class="tags" href="/C.html" title=c>class="token number">0class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">;
class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">}
class="tags" href="/C.html" title=c>code>

问题分析

  • 在 <class="tags" href="/C.html" title=c>code>testclass="tags" href="/C.html" title=c>code> 函数中࿰class="tags" href="/C.html" title=c>c;变量 <class="tags" href="/C.html" title=c>code>aclass="tags" href="/C.html" title=c>code> 是局部变量࿰class="tags" href="/C.html" title=c>c;存储在栈中。当函数执行完毕后࿰class="tags" href="/C.html" title=c>c;<class="tags" href="/C.html" title=c>code>aclass="tags" href="/C.html" title=c>code> 所在的栈帧被释放࿰class="tags" href="/C.html" title=c>c;其地址变得无效。
  • 指针 <class="tags" href="/C.html" title=c>code>pclass="tags" href="/C.html" title=c>code> 存储了 <class="tags" href="/C.html" title=c>code>aclass="tags" href="/C.html" title=c>code> 的地址࿰class="tags" href="/C.html" title=c>c;然而此时 <class="tags" href="/C.html" title=c>code>pclass="tags" href="/C.html" title=c>code> 成为了悬空指针࿰class="tags" href="/C.html" title=c>c;继续通过 <class="tags" href="/C.html" title=c>code>pclass="tags" href="/C.html" title=c>code> 访问该内存区域会导致未定义行为࿰class="tags" href="/C.html" title=c>c;可能引发程序崩溃或输出错误数据。
    class="tags" href="/C.html" title=c>c="https://i-blog.class="tags" href="/C.html" title=c>csdnimg.class="tags" href="/C.html" title=c>cn/direclass="tags" href="/C.html" title=c>ct/f174eb4775f94class="tags" href="/C.html" title=c>c6bb7a04d0f9035b4e9.png#piclass="tags" href="/C.html" title=c>c_right" alt="在这里插入图片描述" width="1" />

解决方法

class="tags" href="/C.html" title=c>c="https://i-blog.class="tags" href="/C.html" title=c>csdnimg.class="tags" href="/C.html" title=c>cn/direclass="tags" href="/C.html" title=c>ct/f174eb4775f94class="tags" href="/C.html" title=c>c6bb7a04d0f9035b4e9.png#piclass="tags" href="/C.html" title=c>c_right" alt="在这里插入图片描述" width="1" />

  1. 避免返回局部变量的地址

    • 可以通过动态内存分配或者静态变量来替代返回局部变量的地址。

    示例 1:动态内存分配

    <class="tags" href="/C.html" title=c>code class="tags" href="/C.html" title=c>class="prism language-class="tags" href="/C.html" title=c>c">class="tags" href="/C.html" title=c>class="token keyword">intclass="tags" href="/C.html" title=c>class="token operator">* class="tags" href="/C.html" title=c>class="token funclass="tags" href="/C.html" title=c>ction">testclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">(class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">) class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">{class="tags" href="/C.html" title=c>class="token keyword">intclass="tags" href="/C.html" title=c>class="token operator">* a class="tags" href="/C.html" title=c>class="token operator">= class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">(class="tags" href="/C.html" title=c>class="token keyword">intclass="tags" href="/C.html" title=c>class="token operator">*class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">)class="tags" href="/C.html" title=c>class="token funclass="tags" href="/C.html" title=c>ction">malloclass="tags" href="/C.html" title=c>cclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">(class="tags" href="/C.html" title=c>class="token keyword">sizeofclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">(class="tags" href="/C.html" title=c>class="token keyword">intclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">)class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">)class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">; class="tags" href="/C.html" title=c>class="token class="tags" href="/C.html" title=c>comment">// 动态分配内存class="tags" href="/C.html" title=c>class="token operator">*a class="tags" href="/C.html" title=c>class="token operator">= class="tags" href="/C.html" title=c>class="token number">10class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">;class="tags" href="/C.html" title=c>class="token keyword">return aclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">; class="tags" href="/C.html" title=c>class="token class="tags" href="/C.html" title=c>comment">// 返回分配的内存地址
    class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">}class="tags" href="/C.html" title=c>class="token keyword">int class="tags" href="/C.html" title=c>class="token funclass="tags" href="/C.html" title=c>ction">mainclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">(class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">) class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">{class="tags" href="/C.html" title=c>class="token keyword">intclass="tags" href="/C.html" title=c>class="token operator">* p class="tags" href="/C.html" title=c>class="token operator">= class="tags" href="/C.html" title=c>class="token funclass="tags" href="/C.html" title=c>ction">testclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">(class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">)class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">;class="tags" href="/C.html" title=c>class="token funclass="tags" href="/C.html" title=c>ction">printfclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">(class="tags" href="/C.html" title=c>class="token string">"%d\n"class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">, class="tags" href="/C.html" title=c>class="token operator">*pclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">)class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">; class="tags" href="/C.html" title=c>class="token class="tags" href="/C.html" title=c>comment">// 正常访问class="tags" href="/C.html" title=c>class="token funclass="tags" href="/C.html" title=c>ction">freeclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">(pclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">)class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">;            class="tags" href="/C.html" title=c>class="token class="tags" href="/C.html" title=c>comment">// 用完后释放内存class="tags" href="/C.html" title=c>class="token keyword">return class="tags" href="/C.html" title=c>class="token number">0class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">;
    class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">}
    class="tags" href="/C.html" title=c>code>

    示例 2:使用静态变量

    <class="tags" href="/C.html" title=c>code class="tags" href="/C.html" title=c>class="prism language-class="tags" href="/C.html" title=c>c">class="tags" href="/C.html" title=c>class="token keyword">intclass="tags" href="/C.html" title=c>class="token operator">* class="tags" href="/C.html" title=c>class="token funclass="tags" href="/C.html" title=c>ction">testclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">(class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">) class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">{class="tags" href="/C.html" title=c>class="token keyword">staticlass="tags" href="/C.html" title=c>c class="tags" href="/C.html" title=c>class="token keyword">int a class="tags" href="/C.html" title=c>class="token operator">= class="tags" href="/C.html" title=c>class="token number">10class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">; class="tags" href="/C.html" title=c>class="token class="tags" href="/C.html" title=c>comment">// 静态变量࿰class="tags" href="/C.html" title=c>c;生命周期贯穿程序运行class="tags" href="/C.html" title=c>class="token keyword">return class="tags" href="/C.html" title=c>class="token operator">&aclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">;         class="tags" href="/C.html" title=c>class="token class="tags" href="/C.html" title=c>comment">// 返回静态变量的地址
    class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">}class="tags" href="/C.html" title=c>class="token keyword">int class="tags" href="/C.html" title=c>class="token funclass="tags" href="/C.html" title=c>ction">mainclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">(class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">) class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">{class="tags" href="/C.html" title=c>class="token keyword">intclass="tags" href="/C.html" title=c>class="token operator">* p class="tags" href="/C.html" title=c>class="token operator">= class="tags" href="/C.html" title=c>class="token funclass="tags" href="/C.html" title=c>ction">testclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">(class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">)class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">;class="tags" href="/C.html" title=c>class="token funclass="tags" href="/C.html" title=c>ction">printfclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">(class="tags" href="/C.html" title=c>class="token string">"%d\n"class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">, class="tags" href="/C.html" title=c>class="token operator">*pclass="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">)class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">; class="tags" href="/C.html" title=c>class="token class="tags" href="/C.html" title=c>comment">// 正常访问class="tags" href="/C.html" title=c>class="token keyword">return class="tags" href="/C.html" title=c>class="token number">0class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">;
    class="tags" href="/C.html" title=c>class="token punclass="tags" href="/C.html" title=c>ctuation">}
    class="tags" href="/C.html" title=c>code>
  2. 确保指针始终指向有效内存

    • 在函数中返回指针时࿰class="tags" href="/C.html" title=c>c;必须确保返回的指针指向的内存是有效的࿰class="tags" href="/C.html" title=c>c;且不会在函数执行完毕后失效。
  3. 使用内存管理工具

    • 现代的内存管理工具(如 Valgrind 或 AddressSanitizer)可以有效地检测悬空指针问题࿰class="tags" href="/C.html" title=c>c;帮助开发者在开发和测试阶段发现和修复内存管理错误。

💯小结

  • class="tags" href="/C.html" title=c>c="https://i-blog.class="tags" href="/C.html" title=c>csdnimg.class="tags" href="/C.html" title=c>cn/direclass="tags" href="/C.html" title=c>ct/76854class="tags" href="/C.html" title=c>c469808448b9ba55a18730class="tags" href="/C.html" title=c>c9e11.png#piclass="tags" href="/C.html" title=c>c_class="tags" href="/C.html" title=c>center" alt="在这里插入图片描述" />在 C语言编程 中࿰class="tags" href="/C.html" title=c>c;指针的管理是至关重要的环节。C语言赋予开发者直接操作内存的能力࿰class="tags" href="/C.html" title=c>c;使得程序能够具备极高的性能class="tags" href="/C.html" title=c>c;但这种能力也伴随着巨大的责任
    开发者需要掌握 指针的生命周期 以及它们在内存中的行为class="tags" href="/C.html" title=c>c;从而确保程序的稳定安全。在大型项目中࿰class="tags" href="/C.html" title=c>c;内存管理指针操作尤为重要࿰class="tags" href="/C.html" title=c>c;团队开发时需要制定明确的标准代码规范class="tags" href="/C.html" title=c>c;以避免因个人疏忽导致的<class="tags" href="/C.html" title=c>code>指针错误class="tags" href="/C.html" title=c>code>。
    此外࿰class="tags" href="/C.html" title=c>c;测试代码审查也应作为内存管理的重要环节࿰class="tags" href="/C.html" title=c>c;以确保代码在各种边界条件下都能正确运行

class="tags" href="/C.html" title=c>c="https://img-blog.class="tags" href="/C.html" title=c>csdnimg.class="tags" href="/C.html" title=c>cn/direclass="tags" href="/C.html" title=c>ct/00d4fdeb7b0d4dbb99e88f325ef249d8.gif#piclass="tags" href="/C.html" title=c>c_class="tags" href="/C.html" title=c>center" alt="在这里插入图片描述" width="1000" height="100" />


class="tags" href="/C.html" title=c>class="blog-vote-box">

http://www.ppmy.cn/news/1550016.html

相关文章

navicat密码解密python

其他资料都是用php写的&#xff0c;但是运行起来好像有点问题&#xff0c;提供python代码&#xff0c;首先注册表获取加密后的密码&#xff0c;然后运行下述代码解密。 参考&#xff1a;获取navicat密码 import hashlib from Crypto.Cipher import AES, Blowfish from Crypto.…

内存不足引发C++程序闪退崩溃问题的分析与总结

目录 1、内存不足一般出现在32位程序中 2、内存不足时会导致malloc或new申请内存失败 2.1、malloc申请内存失败&#xff0c;返回NULL 2.2、new申请内存失败&#xff0c;抛出异常 3、内存不足项目实战案例中相关细节与要点说明 3.1、内存不足导致malloc申请内存失败&#…

【Pytest+Yaml+Allure】实现接口自动化测试框架

一、框架思想 requestsyamlpytestallure实现接口自动化框架。结合数据驱动和分层思想&#xff0c;将代码与数据分离&#xff0c;易维护&#xff0c;易上手。使用yaml编写编写测试用例&#xff0c;利用requests库发送请求&#xff0c;使用pytest管理用例&#xff0c;allure生成…

Linux常用指令(1)

目录 何为指令 基本常用指令 1.clear 2.exit 3.whoami 4.pwd 5.which 6.alias 7.tree ls指令 pwd指令 cd指令 touch指令 mkdir指令 rmdir指令 && rm指令 rmdir指令 rm指令 man指令 cp指令 何为指令 指令的本质其实就是可执行程序。 指令 可执行文件…

第十章 作业

在网页中显示一个工作中的“数字时钟” <!DOCTYPE html> <html><head><meta charset"utf-8"><title>动态时钟</title><style>.all{width: 600px;height: 300px;margin: 100px auto;text-align: center;font-size: 50px;}…

(vue)el-tag标签展开收起效果实现

(vue)el-tag标签展开收起效果实现 效果&#xff1a; 收起: 展开&#xff1a; 实现方法 父组件 <el-form-item class"historay-form-item" label"历史文件"><UploadList ref"uploadListRef" /> </el-form-item><script…

rabbitmq exchange queue topic的关系

在RabbitMQ中&#xff0c;Exchange、Queue 和 Topic 是三个核心概念&#xff0c;它们之间有着密切的关系。理解这些概念及其相互作用对于正确使用RabbitMQ非常重要。下面是对这三个概念的详细解释以及它们之间的关系&#xff1a; 1. Exchange&#xff08;交换器&#xff09; …

Sortable插件实现最简单的拖拽效果

1.安装并引入Sortable插件 2.直接获取需要拖动的dom节点 <template><div><ul id"list"><li v-for"item in list1" :key"item.id" :data-id"item.id" v-on:drag"saveDragItem">{{ item.name }}<…