我的程序需要对vector<string>
的信号处理程序中的SIGINT
内容执行只读访问。 (另一种方法是使用固定大小的固定长度C字符串数组。)该程序设计为在POSIX环境中运行。
vector::operator[]
和vector::size()
异步安全(或信号安全)吗?
答案 0 :(得分:5)
当抽象机器的处理被接收到信号中断时,对象的值就是这样 不是
类型为
在执行信号处理程序期间未指定volatile std::sig_atomic_t
的- 也不是
- 无锁原子对象(29.4)
,并且任何对象的值都不在其中任何一个中 处理程序修改的两个类别变为未定义。
答案 1 :(得分:3)
考虑到C ++,Angew的回答是正确的。既然问题提到了可以提供更强保证的POSIX环境,那么还需要另一个答案,即:
如果进程是多线程的,或者进程是单线程的,并且执行信号处理程序而不是由于:
调用
abort()
,raise()
,kill()
,pthread_kill()
或sigqueue()
以生成未阻止信号的流程未解除阻止并在取消阻止的呼叫之前发送待处理信号
如果信号处理程序引用具有静态存储持续时间的
errno
以外的任何对象,而不是通过为声明为volatile sig_atomic_t
的对象赋值,或者信号处理程序调用任何对象,则行为未定义本标准中定义的函数不是下表中列出的函数之一。
Source: The Open Group Base Specifications Issue 7 IEEE Std 1003.1, 2013 Edition, 2.4.3
这是......仍然是一个非常弱的保证。据我所知:
vector::operator[]
不安全。 固定数组不安全。如果数组是非静态的,则访问固定数组是安全的。
为什么呢? vector::operator[]
没有确切地说明它应该如何实现,只有前置条件和后置条件。可以访问数组的元素(如果数组是非静态的),这意味着如果您之前创建指针(使用vec.data()
或&vec[0]
),则对矢量元素的访问也是安全的发信号,然后通过指针访问元素。
sigaction
函数 - 使用signal
你只能访问信号处理程序中的本地数组,但使用{{1}您可以提供自动和动态数组的指针。尽管在信号处理程序中做尽可能少的建议仍然适用于此。
结论:您在信号处理程序中做得太多了。尝试尽可能少。一种方法是分配一个标志(类型sigaction
),然后返回。代码可以稍后检查标志是否被触发(例如在事件循环中)
答案 2 :(得分:1)
我相信,如果您知道原因对矢量的访问不安全,那么您可以解决它。请注意,访问仍然并不能保证安全。但它适用于任何不是死亡站9000的东西。
如果您直接编程到硬件,信号处理程序会中断程序的执行,就像中断处理程序一样。操作系统只是停止执行您的程序,任何地方。这可能是任何事情的中间。例如,如果向量中添加了元素并且正在更新其大小值,或者它正在将内容复制到新的较长向量,则可能会被信号中断。然后你的信号处理程序将尝试从向量中读取导致灾难。
只要信号处理程序实际上是常量,就可以从信号处理程序中访问该向量。如果你在程序启动时设置了整个程序,然后再也没有写入它,那么使用它是安全的。注意,根据标准文件使用不安全,但有效安全。
这很像单核CPU上的多线程。
现在,如果你确实需要在程序运行时更新向量,你需要通过屏蔽信号或在更新向量之前禁用处理程序来“锁定”信号处理程序,以确保处理程序赢得'在向量处于不一致状态时运行。