什么时候是 std::process::exit` O.K。使用?

When is `std::process::exit` O.K. to use?

documentation of std::process::exit 说:

If a clean shutdown is needed it is recommended to only call this function at a known point where there are no more destructors left to run.

可能由于我缺乏系统编程背景,我不知道是否有析构函数留给 运行 在特定点上,我是否应该关心。我唯一想到的是挂起对文件(或其他东西)的写入操作,最好让文件保持干净状态。

还有什么需要注意的吗?我怀疑在更大、更复杂的程序中使用它是不可取的,但对于小工具来说似乎很方便。

简答:

  • 几乎在所有情况下都使用 panic!()
  • 你几乎可以确保没有析构函数留给运行,如果...
    • ...您在 main() 函数中
    • ...您手动处理堆栈,包括展开(您可能不是...)
  • 有时您可以在退出程序时忽略析构函数,但您需要小心!

稍微长一点的解释

[...] for small tools it seems convenient.

如果由于不可恢复的错误而想退出程序,推荐的方法是panic!()。这将展开堆栈(运行 所有析构函数)并使用附加信息(包括您可以指定的消息字符串)退出程序。

[...] if there are destructors left to run at a specific point and if I should care.

如果在您当前的堆栈框架或上面的任何堆栈框架中有实现 Drop 的局部变量,则 个析构函数留给 运行。堆栈帧是堆栈内存中的一个区域,用于保存函数调用的所有局部变量(松散地说)。函数退出后,丢弃所有局部变量,包括调用所有实现Drop的变量的析构函数。

某些析构函数需要 运行 的概率随着堆栈的深度而增长(“在 main() 和您当前的堆栈框架之间调用了多少函数)。因此很难推理每当您不在 main() 功能中时,请与此相关。


类型什么时候实现 Drop?如果只是 忽略 它们是错误的。考虑一个 i32:当我们退出函数时,我们可以将它留在堆栈内存中,因为它没有任何负面影响(暂时忽略数据安全的特殊情况)。但是,确实有很多类型需要实现Drop。以下是几个类别:

  • 分配堆内存:Box<T>Vec<T>HashMap<T>、...
  • 持有 OS 资源:FileSocket、...
  • 返回句柄:RefMutexGuard、...
  • ...

不是运行对那些有不同效果的析构函数。第一组可能是最无害的:我们会泄漏内存。但是当你退出你的程序时,操作系统无论如何都会清理所有这些内存。 OS 资源几乎相同:文件描述符通常在程序退出时被操作系统删除。

但是 运行 析构函数还有更多理由。要考虑的重要一点:您通常不知道 为什么 某些类型实现 Drop,但这些类型确实依赖于它。当您忽略它时,某些不想要的事情 可能会 发生。通常你不会真正注意到,但有时它会导致严重的问题。