4

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

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

4

3 回答 3

5

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

当抽象机的处理因接收到信号而中断时,既不是

  • 类型volatile std::sig_atomic_t也不是
  • 无锁原子对象 (29.4)

在信号处理程序执行期间未指定,并且处理程序修改的任何不在这两个类别中的任何一个对象的值都将变为未定义。

于 2014-10-07T18:04:56.743 回答
3

考虑到 C++,Angew 的回答是正确的。既然问题提到了可以提供更强保证的 POSIX 环境,这就需要另一个答案,即:

如果进程是多线程的,或者如果进程是单线程的并且执行了信号处理程序,而不是作为以下结果:

  • 进程调用abort(), raise(), kill(), pthread_kill(), 或sigqueue()生成未被阻塞的信号

  • 一个挂起的信号在解除阻塞的调用返回之前被解除阻塞并被传递

如果信号处理程序引用除errno静态存储持续时间以外的任何对象(而不是通过为声明为 的对象分配值)volatile sig_atomic_t,或者如果信号处理程序调用本标准中定义的任何函数而不是列出的函数之一,则行为未定义下表。

来源:开放组基本规范第 7 期 IEEE Std 1003.1,2013 版,2.4.3

这......仍然是一个非常薄弱的​​保证。据我所知:

vector::operator[]不安全。固定数组不安全。如果数组是非静态的,则访问固定数组是安全的。

为什么?vector::operator[]没有具体说明它应该如何实现,只有前置条件和后置条件。可以访问数组的元素(如果数组是非静态的),这意味着如果在发出信号之前创建指针(使用vec.data()or &vec[0]),然后通过指针访问元素,则访问向量元素也是安全的.

编辑:最初我错过了这一点,因为我不知道这个sigaction函数 -signal你只能在信号处理程序中访问你的本地数组,但sigaction你可以提供指向自动和动态数组的指针。不过,在信号处理程序中尽可能少做的建议在这里仍然适用。

底线:您在信号处理程序中做的太多了。尽量少做。一种方法是分配一个标志(类型volatile sig_atomic_t),然后返回。代码可以稍后检查标志是否被触发(例如在事件循环中)

于 2014-10-07T20:26:57.097 回答
1

我相信,如果您知道访问向量不安全的原因,那么您可以解决它。请注意,访问仍然不能保证安全。但它适用于任何不是死亡站 9000 的东西。

如果您直接对硬件进行编程,信号处理程序会中断程序的执行,就像中断处理程序一样。操作系统只是停止执行你的程序,无论它在哪里。这可能在任何事情的中间。例如,如果您的向量中添加了元素并且它正在更新其大小值,或者将内容复制到一个新的、更长的向量中,则可能会被信号中断。然后您的信号处理程序将尝试从向量中读取,从而导致灾难。

您可以从信号处理程序访问向量,只要它有效地保持不变。如果你在程序启动时设置了整个东西,然后再也不写了,那么使用它是安全的。注意,根据标准文件使用不安全,但有效安全。

这很像单核 CPU 上的多线程。

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

于 2014-10-07T22:22:21.320 回答