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

devtools/2024/11/26 7:59:52/
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/devtools/137064.html

相关文章

【C语言】传值调用与传址调用:深度解析与实现

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C语言 文章目录 &#x1f4af;前言&#x1f4af;什么是传值调用和传址调用&#xff1f;1. 传值调用&#xff08;Call by Value&#xff09;2. 传址调用&#xff08;Call by Reference&#xff09; &#x1f4af;传值调…

【C++篇】排队的艺术:用生活场景讲解优先级队列的实现

文章目录 须知 &#x1f4ac; 欢迎讨论&#xff1a;如果你在学习过程中有任何问题或想法&#xff0c;欢迎在评论区留言&#xff0c;我们一起交流学习。你的支持是我继续创作的动力&#xff01; &#x1f44d; 点赞、收藏与分享&#xff1a;觉得这篇文章对你有帮助吗&#xff1…

vue3.5

响应式属性解构 import { watchEffect } from vueconst { count } defineProps([count])watchEffect(() > {// 每次父组件中的 count 属性变化时都会触发这个日志console.log(count) }) useTemplateRef 获取 dom // MyComposable 封装的方法 获取dom export const useMy…

【GIT】TortoiseGit的变基(Rebase)操作

在 TortoiseGit 中&#xff0c;变基&#xff08;Rebase&#xff09; 是一个 Git 的高级操作&#xff0c;用来重新整理分支的提交记录&#xff0c;使它们的历史更加线性化。 1. 什么是变基&#xff1f; 变基的主要作用是将一个分支上的提交“移动”到另一个分支的末尾&#xff…

观察者模式和发布订阅模式

文章目录 手写观察者模式手写发布订阅模式 观察者模式 Subject 和 Observer 直接绑定&#xff0c;中间无媒介。如点击事件&#xff0c;事件直接和按钮进行绑定。 发布订阅模式 Publisher 和 Observer 相互不认识&#xff0c;中间有媒介。如在 A 组件中绑定一个事件&#xff…

SpringBoot(三十六)SpringBoot使用sentinel自定义注解实现限流

前边我们学习了阿里的限流工具sentinel。她是有一个SentinelResource注解可以使用的&#xff0c;但是呢&#xff0c;使用SentinelResource注解需要链接sentinel控制台&#xff0c;在控制台中创建对应的规则。 再在对应的方法中使用SentinelResource注解来配置功能。 但是呢&…

python操作Elasticsearch

使用elasticsearch 6.x版本&#xff0c;操作es数据。 #! -*- coding:utf-8 -* import timefrom elasticsearch import Elasticsearch, helpersclass EstUtil:_instance Nonedef __new__(cls, *args, **kwargs):if not cls._instance:cls._instance super(EstUtil, cls).__ne…

【论文笔记】Number it: Temporal Grounding Videos like Flipping Manga

&#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&#xff0c;为生民立命&#xff0c;为往圣继绝学&#xff0c;为万世开太平。 基本信息 标题: Number it: Temporal Grou…