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

ops/2024/11/26 9:33:44/
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/ops/136798.html

相关文章

简单的爬虫脚本编写

一、数据来源分析 想爬取一个网站的数据&#xff0c;我们首先要进行数据分析。通过浏览器F12开发者工具栏进行抓包&#xff0c;可以分析我们想要的数据来源。 通过关键字搜索&#xff0c;可以找到相对应的数据包 二、爬虫实现 需要用到的模块为&#xff1a;request&#xf…

NVR小程序接入平台EasyNVR多品牌NVR管理工具:高效管理分散视频资源的解决方案

在当今数字化、智能化的时代背景下&#xff0c;视频监控已成为各行各业不可或缺的一部分&#xff0c;从公共安全到企业运维&#xff0c;再到智慧城市建设&#xff0c;视频资源的管理与应用正面临着前所未有的挑战。如何高效整合、管理这些遍布各地的分散视频资源&#xff0c;成…

单机部署kubernetes环境下Overleaf-基于MicroK8s的Overleaf应用部署指南

在本文中&#xff0c;我们将探讨如何使用MicroK8s在本地或云环境中快速部署Overleaf应用。MicroK8s是一个轻量级的Kubernetes发行版&#xff0c;它为开发者提供了一个简单的方式来部署和管理容器化应用。 需要使用Kompose转换Overleaf官方Docker Compose配置得到适用于kuberne…

数据结构——排序算法第一幕(插入排序:直接插入排序、希尔排序 选择排序:直接选择排序,堆排序)超详细!!!!

文章目录 前言一、排序1.1 概念1.2 常见的排序算法 二、插入排序2.1 直接插入排序2.2 希尔排序希尔排序的时间复杂度 三、选择排序3.1 直接选择排序3.2 堆排序 总结 前言 时间很快&#xff0c;转眼间已经到数据结构的排序算法部分啦 今天我们来学习排序算法当中的 插入排序 和 …

docker部署redis,并设置密码

获取官方镜像 redis:7.4.1 准备配置文件 文件 redis.conf requirepass xxx密码请自行设置 准备启动脚本 start_redis.sh 注意&#xff1a; 要把这个脚本和上面的redis.conf放到同一个目录下。 workdir$(cd $(dirname $0); pwd) redis_id"$(docker ps -a| grep red…

C# Winform 五子棋小游戏源码

文章目录 1.设计来源五子棋小游戏讲解1.1 主界面1.2 对弈棋盘界面1.3 对弈结束界面 2.效果和源码2.1 动态效果2.2 源代码 源码下载万套模板&#xff0c;程序开发&#xff0c;在线开发&#xff0c;在线沟通 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/…

图像拟合算法全解析:从基础原理到前沿实践

摘要&#xff1a; 本文全面且深入地阐述了多种图像拟合算法&#xff0c;涵盖线性回归、多项式拟合、最小二乘法拟合、高斯拟合以及基于深度学习的图像拟合方法等。针对每种算法&#xff0c;详细剖析其原理、数学模型、具体实现步骤&#xff0c;并细致探讨它们的优缺点与适用场景…

redis的map底层数据结构 分别什么时候使用哈希表(Hash Table)和压缩列表(ZipList)

在Redis中&#xff0c;Hash数据类型的底层数据结构可以是压缩列表&#xff08;ZipList&#xff09;或者哈希表&#xff08;HashTable&#xff09;。这两种结构的使用取决于特定的条件&#xff1a; 1. **使用ZipList的条件**&#xff1a; - 当Hash中的数据项&#xff08;即f…