在信号处理程序中使用 std::shared_ptr 和 std::weak_ptr 是否安全?
Is it safe to use `std::shared_ptr` and `std::weak_ptr` in a signal handler?
我知道从信号处理程序直接或间接调用 malloc
或 free
是不安全的。
但是,如果我能保证至少有一个共享引用将保持活动状态,那么复制构造和销毁额外的共享或弱引用是否安全,或者我是否必须滚动我自己的引用计数?
(是的,我知道信号处理程序 通常 不应该做太多。但这次我有一个很好的理由。)
C++标准定义了"plain old function"的概念如下:
A POF (“plain old function”) is a function that uses only features from [the C/C++] common subset, and that does not directly or indirectly use any function that is not a POF, except that it may use plain lock-free atomic operations.
此外:
The behavior of any function other than a POF used as a signal handler in a C++ program is implementation-defined.
显然,C++ class 对象不是 C/C++ 公共子集的一部分,因此在信号处理程序中使用它们会产生实现定义的行为。
现在,许多实现将允许您有限地使用 C++ 功能。如果您的实现不允许内存分配或异常,那么这就是我们对这些智能指针类型的了解。
然后所有 weak_ptr
constructors 都显式声明 noexcept
。所以他们不能抛出异常。这也意味着他们不允许分配内存(因为分配内存失败会引发异常)。是的,他们可以分配内存和 std::terminate
如果它失败了,但这对于实现来说是非常粗鲁的。
与copy&move constructors of shared_ptr
类似的是noexcept
,同理。 shared_ptr
.
的别名构造函数也是如此
如果您绝对确定至少有一个 shared_ptr
仍然存在,那么销毁 shared_ptr
被明确声明没有副作用。这可能包括内存取消分配。
这些是标准库给你的保证。
我知道从信号处理程序直接或间接调用 malloc
或 free
是不安全的。
但是,如果我能保证至少有一个共享引用将保持活动状态,那么复制构造和销毁额外的共享或弱引用是否安全,或者我是否必须滚动我自己的引用计数?
(是的,我知道信号处理程序 通常 不应该做太多。但这次我有一个很好的理由。)
C++标准定义了"plain old function"的概念如下:
A POF (“plain old function”) is a function that uses only features from [the C/C++] common subset, and that does not directly or indirectly use any function that is not a POF, except that it may use plain lock-free atomic operations.
此外:
The behavior of any function other than a POF used as a signal handler in a C++ program is implementation-defined.
显然,C++ class 对象不是 C/C++ 公共子集的一部分,因此在信号处理程序中使用它们会产生实现定义的行为。
现在,许多实现将允许您有限地使用 C++ 功能。如果您的实现不允许内存分配或异常,那么这就是我们对这些智能指针类型的了解。
然后所有 weak_ptr
constructors 都显式声明 noexcept
。所以他们不能抛出异常。这也意味着他们不允许分配内存(因为分配内存失败会引发异常)。是的,他们可以分配内存和 std::terminate
如果它失败了,但这对于实现来说是非常粗鲁的。
与copy&move constructors of shared_ptr
类似的是noexcept
,同理。 shared_ptr
.
如果您绝对确定至少有一个 shared_ptr
仍然存在,那么销毁 shared_ptr
被明确声明没有副作用。这可能包括内存取消分配。
这些是标准库给你的保证。