C语言中的悬空指针



C语言中的悬空指针

C语言中的**悬空指针**用于描述当一个指针的目标(它指向的变量)已被释放或不再可访问时,该指针的行为。换句话说,C语言中的**悬空指针**是指向无效变量(不属于适当类型)的指针。

为什么C语言中会出现悬空指针?

使用悬空指针可能会导致C程序出现不可预测的行为,有时甚至会导致程序崩溃。悬空指针的情况可能由于以下原因导致:

  • 内存释放
  • 访问越界内存位置
  • 当变量超出作用域时

让我们通过示例分析这三种情况。

内存释放

指针保存变量的地址。如果目标变量被释放,则其指针变成悬空指针。尝试访问其目标变量已被释放的指针会导致垃圾值。

让我们使用malloc()创建一个整数变量并将它的地址存储在一个整数指针中。

int *x = (int *) malloc(sizeof(int));
*x = 100;

这里,指针引用内存中的一个有效位置。让我们使用free()函数释放“x”指向的内存。

free(x);

现在,“x”存储了一个不再有效的地址。因此,如果我们尝试对其进行解引用,编译器会显示某个垃圾值。

示例

以下示例展示了如何在C程序中最终得到悬空指针:

#include <stdio.h>

int main(){

   int *x = (int *) malloc(sizeof(int));
   *x = 100;
   printf("x: %d\n", *x);

   free (x);
   printf("x: %d\n", *x);
}

输出

运行代码并检查其输出:

x: 100
x: 11665744

访问越界内存位置

我们知道函数可以返回一个指针。如果它返回指向函数内部任何局部变量的指针,则会导致在外部作用域中出现悬空指针,因为其指向的位置不再有效。

示例

请查看以下代码:

#include <stdio.h>

int * function();

int main(){

   int *x = function();
   printf("x: %d", *x);
   return 0;
}

int * function(){
   int a =100;
   return &a;
}

输出

编译时,在函数中的“return &a”语句处会显示以下警告

warning: function returns address of local variable [-Wreturn-local-addr]

尽管有警告,但如果运行程序,则会得到以下错误

Segmentation fault (core dumped)

出现此错误时,表示程序正在尝试访问越界的内存位置。

当变量超出作用域时

当在内部块中声明的变量在外部被访问时,也会出现同样的原因。在以下示例中,我们在一个块中有一个变量,其地址存储在一个指针变量中。

但是,在块外部,指针成为悬空指针,因为其目标超出范围。

示例

以下程序演示了当其基变量超出作用域时如何得到悬空指针:

#include <stdio.h>

int main(){
   int *ptr;{
      int a = 10;
      ptr = &a;
   }

   // 'a' is now out of scope
   // ptr is a dangling pointer now
   printf("%d", ptr);

   return 0;
}

输出

它将显示一个垃圾值:

6422036

如何修复悬空指针?

C语言没有自动垃圾回收功能,因此我们需要仔细管理动态分配的内存。

要修复悬空指针问题或完全避免它们,您需要应用正确的内存管理,并尝试避免可能导致悬空指针的情况。

以下是一些可以遵循的一般准则,以避免悬空指针:

  • 始终确保在释放内存后将指针设置为NULL。这将清楚地表明指针不再指向有效内存位置。
  • 避免访问超出作用域的变量或内存位置。
  • 不要返回指向局部变量的指针,因为此类局部变量将在函数返回时超出作用域。

遵循这些准则,可以减少代码中出现悬空指针的可能性。

广告