首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么这段代码没有出现分段错误?(总线错误)

为什么这段代码没有出现分段错误?(总线错误)
EN

Stack Overflow用户
提问于 2012-03-08 01:45:27
回答 6查看 484关注 0票数 4

我的代码中有一个bug,是这样的。

代码语言:javascript
运行
复制
char desc[25];
char name[20];
char address[20];
sprintf (desc, "%s %s", name, address);

理想情况下,这应该会给出一个段错误。然而,我看到这给出了一个总线错误。维基百科说:“当程序试图访问未对齐的内存位置时,或者当您试图访问不存在或不允许访问的物理(非虚拟)内存位置时,就会出现总线错误。”

上述陈述的第二部分听起来类似于凹陷断层。所以我的问题是,什么时候会有SIGBUS,什么时候会有SIGSEGV?

编辑:-相当多的人提到了上下文。我不确定需要什么上下文,但这是一个缓冲区溢出,它位于一个静态类函数中,该函数从许多其他类函数调用。如果有什么我可以提供的更具体的东西会有所帮助,请尽管问。

无论如何,有人评论说,我应该写更好的代码。我想问这个问题的重点是“应用程序开发人员可以从SIGBUS和SIGSEGV中推断出什么吗?”(摘自下面的博客帖子)

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2012-03-08 02:29:54

正如您可能意识到的,基本原因是程序中未定义的行为。在这种情况下,它导致由硬件检测到的错误,该错误被OS捕获并映射到信号。确切的映射并不是真正指定的(我见过整数除以零会导致SIGFPE),但通常情况下:当您访问越界时会发生SIGSEGV,当出现其他访问错误时会发生SIGBUS,而对于非法指令则会出现SIGILL。在这种情况下,最有可能的解释是您的边界错误覆盖了堆栈上的返回地址。如果返回地址没有正确对齐,您可能会得到一个SIGBUS,如果对齐了,您将开始执行任何内容,这可能会导致SIGILL。(但将随机字节作为代码执行的可能性是标准委员会在定义“未定义的行为”时所考虑的。特别是在没有内存保护的机器上,您最终可能会直接跳到操作系统中。)

票数 4
EN

Stack Overflow用户

发布于 2012-03-08 01:48:36

当你用内存做可疑的事情时,分段错误是不能保证的。这完全取决于很多因素(编译器如何在内存中布局程序,优化等)。

对于C++程序来说可能是非法的东西在一般情况下对于程序来说可能不是非法的。例如,操作系统并不关心您是否跳出数组。它甚至不知道数组是什么。然而,它会关心你是否触摸了不属于你的记忆。

票数 4
EN

Stack Overflow用户

发布于 2012-03-08 02:05:12

如果您尝试对未映射到进程的虚拟地址进行数据访问,则会发生分段错误。在大多数操作系统上,内存是以几千字节的页进行映射的;这意味着,如果您注销数组的末尾,通常不会得到错误,因为在内存页中,它后面还有其他有效数据。

总线错误表示更低级别的错误;如您所说,错误对齐的访问或丢失的物理地址是两个原因。然而,第一种情况在这里没有发生,因为您正在处理字节,它没有对齐限制;我认为第二种情况只有在内存完全耗尽时才会发生,而这种情况可能不会发生。

然而,我认为如果你试图从一个无效的虚拟地址执行代码,你也可能会得到一个总线错误。这很可能就是这里正在发生的事情--通过删除本地数组的末尾,您将覆盖堆栈帧的重要部分,例如函数的返回地址。这会导致函数返回一个无效的地址,这(我认为)会给出一个总线错误。这就是我最好的猜测,你在这里体验到了什么特殊的未定义行为。

一般来说,您不能依靠分段错误来捕获缓冲区溢出;据我所知,最好的工具是valgrind,尽管它仍然无法捕获某些类型的溢出。在处理字符串时,避免溢出的最好方法是使用std::string,而不是假装正在编写C。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9606540

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档