什么时候是 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 资源:
File
、Socket
、...
- 返回句柄:
Ref
、MutexGuard
、...
- ...
不是运行对那些有不同效果的析构函数。第一组可能是最无害的:我们会泄漏内存。但是当你退出你的程序时,操作系统无论如何都会清理所有这些内存。 OS 资源几乎相同:文件描述符通常在程序退出时被操作系统删除。
但是 运行 析构函数还有更多理由。要考虑的重要一点:您通常不知道 为什么 某些类型实现 Drop
,但这些类型确实依赖于它。当您忽略它时,某些不想要的事情 可能会 发生。通常你不会真正注意到,但有时它会导致严重的问题。
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 资源:
File
、Socket
、... - 返回句柄:
Ref
、MutexGuard
、... - ...
不是运行对那些有不同效果的析构函数。第一组可能是最无害的:我们会泄漏内存。但是当你退出你的程序时,操作系统无论如何都会清理所有这些内存。 OS 资源几乎相同:文件描述符通常在程序退出时被操作系统删除。
但是 运行 析构函数还有更多理由。要考虑的重要一点:您通常不知道 为什么 某些类型实现 Drop
,但这些类型确实依赖于它。当您忽略它时,某些不想要的事情 可能会 发生。通常你不会真正注意到,但有时它会导致严重的问题。