微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决重用悬空指针或空指针时出错分段错误

#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++”

解决方法

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

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

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

90% 的问题是 red herring。整个问题可以在一行中重述:

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

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

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

,

这是未定义的行为。您通过执行 free(title) 告诉操作系统您的程序不再需要内存,但这并不意味着内存会立即从您的进程中获取。相反,title 仍然保留(现在已释放且未考虑)内存的地址,随后的 strcpy()(取决于操作系统及其内存使用策略)可能能够写入该内存和 printf()将获得地址(再次释放和下落不明)并打印字符,直到它到达第一个 \0 之前放在那里的 strcpy()

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。