对向量(vector :: operator []和vector :: size())的只读访问是否是异步安全的?

时间:2014-10-07 17:59:41

标签: c++ vector posix signal-handling async-safe

我的程序需要对vector<string>的信号处理程序中的SIGINT内容执行只读访问。 (另一种方法是使用固定大小的固定长度C字符串数组。)该程序设计为在POSIX环境中运行。

vector::operator[]vector::size()异步安全(或信号安全)吗?

3 个答案:

答案 0 :(得分:5)

不,这不安全。 C ++ 11 1.9 / 6:

  

当抽象机器的处理被接收到信号中断时,对象的值就是这样   不是

     
      类型为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上的多线程。

现在,如果你确实需要在程序运行时更新向量,你需要通过屏蔽信号或在更新向量之前禁用处理程序来“锁定”信号处理程序,以确保处理程序赢得'在向量处于不一致状态时运行。