如果程序的 main returns 是 i32,为什么是 $? (由调用它的 shell 测量)截断为 8 位?

If a program's main returns an i32, why is $? (as measured by the shell that called it) truncated to 8 bits?

很抱歉提出这样一个菜鸟问题,但为什么结果不是 516

define i32 @main()
{
        %1 = add i32 6, 500
        %2 = add i32 5, 5
        %3 = add i32 %1, %2
        ret i32 %3
}

http://llvm.org/docs/LangRef.html#integer-type

i32 a 32-bit integer.

用法:

./lli Program.ir; echo $?
4

提前致谢

Unix中进程的退出码只有8位。无论是否涉及 LLVM,任何较大的值都会被截断:

$ ( exit 516 ); echo $?
4

出口code(我要区分你程序返回的出口value,和出口code 可用于启动您编程的进程)实际上,在类似 UNIX 的操作系统中,是几个 不同 项的集合,一个 其中是退出值。例如,参见 this link,其中包含(我的 强调 [extra information]):

Don't confuse a program's exit status [value] with a process' termination status [code]. There are lots of ways a process can terminate besides having its program finish. In the event that the process termination is caused by program termination (i.e., exit), though, the program’s exit status [value] becomes part of the process' termination status [code].

从进程中获取实际退出状态的宏(参见 here)指出:

If WIFEXITED is true of status, this macro returns the low-order 8 bits of the exit status value from the child process.

Linux exit_group 系统调用的实际源代码也表明了这一点,它最终由 exit:

调用
SYSCALL_DEFINE1(exit_group, int, error_code)
{
    do_group_exit((error_code & 0xff) << 8);
    /* NOTREACHED */
    return 0;
}

你可以看到它只使用退出值的低八位,并将其左移以便它可以将其他项目(控制信息)存储在那里,在这种情况下全部为零。对比来自信号处理器的相同调用,其中设置控制信息:

do_group_exit(ksig->info.si_signo)

换句话说,它还必须在进程退出代码中放入其他东西,例如哪个信号终止了它(如果它被信号终止),它是否转储核心,等等。这就是为什么退出值被限制在比您预期的更小的范围内。

ISO 标准 (C11) 也允许这样做,在 7.22.4.4 The exit function /5 中(因为从 main() 返回整数值等同于使用该值调用 exit()

Finally, control is returned to the host environment. If the value of status is zero or EXIT_SUCCESS, an implementation-defined form of the status successful termination is returned. If the value of status is EXIT_FAILURE, an implementation-defined form of the status unsuccessful termination is returned. Otherwise the status returned is implementation-defined.