繁体   English   中英

重用悬空或 null 指针时出错(分段错误)

[英]Error (Segmentation Fault) while reusing a dangling or null pointer

#include<stdlib.h>
#include<string.h>
int main ( void )
{
  char *title=NULL;
  title = (char *) malloc(15);
  strcpy(title, "C Programming");
  printf("String = %c", *title);
  free(title); 
//   title=NULL;    //or title = 0;
  strcpy(title, "C++");
  printf(" %s", title);
  return 0;
}

当我取消注释“title=NULL”行时,程序因分段错误而崩溃; 有人可以解释这种行为吗

打印 "String = C C++" 否则

如果您的代码取消引用悬空或 null 指针,则行为未定义- 任何事情都可能发生。 这两种可能的行为(“它按预期工作”和“它崩溃”)实际上是未定义行为的最常见表现。

有时,您可以合理化未定义的行为 - 就像在这种情况下一样。 但你不能总是指望它是可以理解的。

  • 如果您的代码尝试将内容写入 null 地址,它会崩溃,因为操作系统可以检测到这一点。 它非常简单(空指针指向一个不可读和不可写的 memory 页面)并且很有用(一个好的调试器会直接停在有问题的代码行)。
  • 如果你的代码试图重用一个悬空指针,它指向的地址通常仍然是可写的free不会告诉操作系统它现在是悬空的。 free只会编辑一些簿记数据结构,因此释放的地址将可用于将来的分配。 访问悬空指针不容易导致崩溃,因为操作系统只能在页面粒度上管理 memory 访问,可以是4 KiB或类似的大小。

90% 的问题是红鲱鱼 整个问题可以用一行来重申:

当我这样做时:title=NULL; strcpy(标题,“C++”); 我的程序崩溃了。 为什么?

上面的代码尝试将字节写入 null 指针引用的 memory 地址。 根据定义,这是未定义的行为。 未定义的行为意味着任何事情都可能发生,例如一碗矮牵牛花和抹香鲸可能会从天上掉下来,但在绝大多数执行环境中,当然在您的执行环境中,null 指针引用的 memory 地址不是可写,因此这将始终导致您遇到的确切行为:分段错误。

此外,为了解决问题的其余部分,当将指针设置为 NULL 的行被注释掉时,您正在写入已释放的 memory 位置。 由于它已被释放,因此不应再次访问它,并且再次访问它是未定义的行为,只有在这种情况下,没有检测到滥用的机制,所以它只是巧合。 尝试在不同的环境中运行相同的程序,就会有成盆的矮牵牛和抹香鲸从天而降。

这是未定义的行为。 您通过执行free(title)告诉操作系统您的程序不再需要 memory 但这并不意味着 memory 会立即从您的进程中取出。 Instead title still holds address of (now freed and not accounted for) memory and subsequent strcpy() (depending on OS and its memory usage policy) might be able to write into that memory and printf() will get address (again freed and unaccounted for) 并将打印字符,直到到达strcpy()放置的第一个\0

当您在释放NULL title ,期望指向已分配 memory 的指针的其他函数(此处为strcpy() )将获得无效输入并失败(出现分段错误)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM