R-R*_*ock 11 c linux segmentation-fault
I\xe2\x80\x99m 在执行 C 程序时遇到以下问题:
\n~$ ./a.out\nzsh IOT instruction (core dumped) ./a.out\nRun Code Online (Sandbox Code Playgroud)\n我\xe2\x80\x99以前从未见过这个,而且我不\xe2\x80\x99不知道如何解决它。它是什么?
\n请注意,我\xe2\x80\x99m 不是在寻找解决此问题的方法,而是了解问题所在,以便我可以修复它。谷歌没有提供任何有帮助的结果。
\nNat*_*dge 32
tl;dr: 这意味着abort()被调用了。现在,你必须弄清楚它为什么被称为。(核心转储可能会有所帮助。)
但是,为什么会出现奇怪的消息?我决定调查一下。
从前,有一台名为PDP-11 的计算机。它有一条名为“I/O Trap”的指令IOT,该指令会导致操作系统陷入某种类型的陷阱。PDP/11 上的 Unix 似乎会通过向进程传递特定信号来处理此陷阱,该信号的数值被分配给SIGIOT中的宏<signal.h>。
现代 Linux 仍然支持该宏,因此硬编码信号宏列表的旧程序仍然可以编译。然而,它被分配给与更常见的相同的数字(6)SIGABRTabort() ,这是调用时发出的信号。所以实际上,SIGIOT它只是 的遗留别名SIGABRT。
但消息呢?我们正在努力做到这一点。请记住,宏名称SIGIOT和SIGABRT仅在编译时存在;在运行时,进程看到的只是整数值 6。要将其转换为人类可读的值,通常的方法是调用标准库strsignal函数。在使用 glibc 的 Linux 上,返回相当合理的strsignal(6)字符串。Aborted这是大多数 shell 用来报告杀死进程的信号的方法。
但 zsh 出于某种原因想要有所不同。他们不使用标准strsignal功能,而是推出自己的功能。他们有一对脚本 ( ),可以解析系统文件以查看存在哪些信号,然后生成一个查找表以将数值映射到预定义的字符串。awk 代码如下所示:signame1.awk signame2.awksignal.h
if (signam == "ABRT") { msg[signum] = "abort" }
if (signam == "ALRM") { msg[signum] = "alarm" }
# ...
if (signam == "IO") { msg[signum] = "i/o ready" }
if (signam == "IOT") { msg[signum] = "IOT instruction" }
if (signam == "KILL") { msg[signum] = "killed" }
# ...
Run Code Online (Sandbox Code Playgroud)
现在你看到了这个问题。由于SIGABRT定义为 6,因此当脚本处理#define SIGABRT 6来自 的行时<signal.h>,它将设置msg[6] = "abort"。那就太好了。但SIGIOT也定义为 6,因此当它开始处理该行时,它将设置,替换之前msg[6] = "IOT instruction"的字符串。
结果,使用 zsh 时,常见的SIGABRT信号会被报告为奇怪的IOT instruction消息。这可以说是 zsh 中的一个小错误。它被报告为 Debian bug,但上游似乎没有报告。
一个更严重的副作用是kill -ABRT在 zsh 下不起作用;要发送中止信号,您必须改为发送中止信号kill -IOT,这可能没有人知道该怎么做。
我刚刚向 zsh-workers 邮件列表发送了一条关于它的消息。