fn main 并不是程序的第一行。这篇看真实的 Mach-O 入口与符号,用 SIGPIPE 的行为差异证明 lang_start 在 main 之前做了事情,再量出 std 的启动开销,最后看 main 返回之后的两种退出方式。
nm 里与启动相关的符号:['__RNCINvNtCskP2HG43Jt7g_3std2rt10lang_startuE0CslUlDIcILRSm_5u130a', '__RNCNCNCNvNtCskP2HG43Jt7g_3std2rt19lang_start_internal00s_0B9_', '__RNSNvYNCINvNtCskP2HG43Jt7g_3std2rt10lang_startuE0INtNtNtCsedRpiqSkYaQ_4core3ops8function6FnOnceuE9call_once6vtableCslUlDIcILRSm_5u130a', '__RNvNtCskP2HG43Jt7g_3std2rt19lang_start_internal'] 入口:['__mh_execute_header', '_main'] 动态依赖(otool -L):['/usr/lib/libSystem.B.dylib'] Mach-O 的 LC_MAIN 入口偏移:2264(指向 C 风格的 main,它再调 lang_start)
程序的编译阶段见Rust 编译阶段。
编译:成功
Rust 往被 head 提前关掉的管道里写:
参数在 main 开始时就已就绪:1 个
Rust 程序退出码(PIPESTATUS):3
写第 478 行时出错:BrokenPipe
对照:C 程序同样的事:
line 0
C 程序退出码(PIPESTATUS):141 C 空 main 平均 2356 µs / 次(含 Python subprocess 的 fork+exec+wait 开销)
Rust #![no_main] 平均 2375 µs / 次(含 Python subprocess 的 fork+exec+wait 开销)
Rust 空 main(std 的 lang_start) 平均 2594 µs / 次(含 Python subprocess 的 fork+exec+wait 开销)
二进制大小: {'C 空 main': '16,840', 'Rust #![no_main]': '16,792', 'Rust 空 main': '431,048'}计时包含 Python subprocess 启动子进程的开销,因此只能比较差值,绝对值没有意义。
编译:成功
运行(退出码 7):
main 里
D 被 drop
编译:成功
运行(退出码 5):
main 里,调用 process::exit(5)panic 与 exit 的关系见panic!、unwrap 与 expect。