HOME> 家族联盟> std::signal

C++

编译器支持

自由(freestanding)与宿主(hosted)

语言

标准库

标准库头文件

具名要求

特性测试宏 (C++20)

语言支持库

概念库 (C++20)

诊断库

内存管理库

元编程库 (C++11)

通用工具库

容器库

迭代器库

范围库 (C++20)

算法库

字符串库

文本处理库

数值库

日期和时间库

输入/输出库

文件系统库 (C++17)

并发支持库 (C++11)

执行控制库 (C++26)

技术规范

符号索引

外部库

[编辑] 工具库

语言支持

类型支持(基本类型、RTTI)

库特性测试宏 (C++20)

程序工具

变参函数

initializer_list(C++11)

is_constant_evaluated(C++20)

is_within_lifetime(C++26)

source_location(C++20)

协程支持 (C++20)

契约支持 (C++26)

三路比较

three_way_comparablethree_way_comparable_with(C++20)(C++20)

strong_ordering(C++20)

weak_ordering(C++20)

partial_ordering(C++20)

common_comparison_category(C++20)

compare_three_way_result(C++20)

compare_three_way(C++20)

strong_order(C++20)

weak_order(C++20)

partial_order(C++20)

compare_strong_order_fallback(C++20)

compare_weak_order_fallback(C++20)

compare_partial_order_fallback(C++20)

is_eqis_ltis_lteq(C++20)(C++20)(C++20)

is_neqis_gtis_gteq(C++20)(C++20)(C++20)

通用工具

函数对象

位操作 (C++20)

bitset

hash(C++11)

关系运算符 (C++20 中弃用)

rel_ops::operator!=rel_ops::operator>

rel_ops::operator<=rel_ops::operator>=

整数比较函数

cmp_equalcmp_lesscmp_less_than(C++20)(C++20)(C++20)

cmp_not_equalcmp_greatercmp_greater_than(C++20)(C++20)(C++20)

in_range(C++20)

交换与类型操作

swap

ranges::swap(C++20)

exchange(C++14)

declval(C++11)

to_underlying(C++23)

forward(C++11)

forward_like(C++23)

move(C++11)

move_if_noexcept(C++11)

as_const(C++17)

常用词汇类型

pair

tuple(C++11)

optional(C++17)

any(C++17)

variant(C++17)

tuple_size(C++11)

tuple_element(C++11)

apply(C++17)

make_from_tuple(C++17)

expected(C++23)

[编辑] 程序支持实用程序

程序终止

abort

exit

quick_exit(C++11)

_Exit(C++11)

atexit

at_quick_exit(C++11)

EXIT_SUCCESSEXIT_FAILURE

不可达控制流

unreachable(C++23)

与环境通信

system

getenv

信号

signal

raise

sig_atomic_t

SIG_DFLSIG_IGN

SIG_ERR

信号类型

SIGABRTSIGFPESIGILL

SIGINTSIGSEGVSIGTERM

非局部跳转

setjmp

longjmp

类型

jmp_buf

[编辑]

定义于头文件

/* signal-handler */* signal( int sig, /* signal-handler */* handler );

(1)

extern "C" using /* signal-handler */ = void(int);

(2)

(仅作说明*)

改变信号 sig 的处理方式。根据 handler 的不同,信号可以被忽略,设置为默认处理,或者由用户定义函数处理。

当信号处理程序被设置为一个函数并且信号发生时,在信号处理程序开始之前是否立即执行 std::signal(sig, SIG_DFL) 是实现定义的。此外,实现可以在信号处理程序运行时阻止某些实现定义的信号集发生。

对于某些信号,实现可以在程序启动时调用 std::signal(sig, SIG_IGN)。对于其余信号,实现必须调用 std::signal(sig, SIG_DFL)。

(注意:POSIX 引入了 sigaction 来标准化这些实现定义的行为)

目录

1 参数

2 返回值

3 信号处理程序

4 注意

5 示例

6 引用

7 缺陷报告

8 参阅

[编辑] 参数

sig

-

要设置信号处理程序的信号。它可以是实现定义的值或以下值之一

SIGABRTSIGFPESIGILLSIGINTSIGSEGVSIGTERM

定义信号类型 (宏常量) [编辑]

处理程序

-

信号处理程序。这必须是以下之一 SIG_DFL 宏。信号处理程序设置为默认信号处理程序。 SIG_IGN 宏。信号被忽略。指向函数的指针。函数的签名必须等同于以下

extern "C" void fun(int sig);

[编辑] 返回值

成功时返回先前的信号处理程序,失败时返回 SIG_ERR(在某些实现上可能禁用设置信号处理程序)。

[编辑] 信号处理程序

对作为信号处理程序安装的用户定义函数施加以下限制。

如果信号处理程序被调用不是因为 std::abort 或 std::raise(异步信号),则在以下情况下行为是未定义的:

信号处理程序调用标准库中的任何函数,除了

std::abort

std::_Exit

std::quick_exit

std::signal,其第一个参数是当前正在处理的信号编号(异步处理程序可以重新注册自身,但不能注册其他信号)。

信号处理程序引用任何具有静态存储持续时间的对象,但不是 std::atomic 或 (自 C++11 起)volatile std::sig_atomic_t 的对象。

(C++17 前)

“*纯粹的无锁原子操作*”是调用 (自 C++23 起) 中的函数 f,使得

f 是函数 std::atomic_is_lock_free, f 是成员函数 is_lock_free (例如 std::atomic::is_lock_free()), f 是 std::atomic_flag 的非静态成员函数, f 是非成员函数,且 f 的第一个参数类型为 *cv* std::atomic_flag*, f 是在一个对象 obj 上调用的非静态成员函数,使得 obj.is_lock_free() 产生 true,或 f 是一个非成员函数,并且对于传递给 f 的每个原子指针参数 arg,std::atomic_is_lock_free(arg) 产生 true。

如果任何信号处理程序执行以下任何操作,则行为是未定义的

调用任何库函数,除了纯无锁原子操作和以下 *信号安全* 函数(请特别注意,动态分配不是信号安全的)

std::signal,其第一个参数是当前正在处理的信号编号(信号处理程序可以重新注册自身,但不能注册其他信号)。std::numeric_limits 的成员函数 std::_Exit

std::abort

std::quick_exit

std::initializer_list 的成员函数,以及 std::begin 和 std::end 的 std::initializer_list 重载 std::forward、std::move、std::move_if_noexcept来自 的所有函数 std::memcpy 和 std::memmove

访问具有线程存储持续时间的对象一个 dynamic_cast 表达式一个 throw 表达式进入 try 块初始化执行动态非局部初始化的静态变量(包括延迟到首次 ODR-use)等待任何具有静态存储持续时间的变量的初始化完成,因为另一个线程正在同时初始化它

(C++17 起)

如果用户定义函数在处理 SIGFPE、SIGILL、SIGSEGV 或任何其他指定计算异常的实现定义信号时返回,则行为未定义。

如果信号处理程序是由于 std::abort 或 std::raise(同步信号)而被调用的,则如果信号处理程序调用 std::raise,则行为未定义。

进入信号处理程序时,浮点环境的状态和所有对象的值都是未指定的,除了

类型为 volatile std::sig_atomic_t 的对象

无锁 std::atomic 类型的对象通过 std::atomic_signal_fence 可见的副作用

(C++11 起)

从信号处理程序返回时,任何由信号处理程序修改的非 volatile std::sig_atomic_t 或无锁 std::atomic 对象的行为都是不确定的。

(直到 C++14)

调用函数 signal() 同步于任何由此导致的信号处理程序调用。

如果信号处理程序是由于调用 std::raise(同步)而执行的,则处理程序的执行 *序列在* std::raise 调用之后,*序列在* 其返回之前,并在与 std::raise 相同的线程上运行。其他信号处理程序的执行与程序的其余部分 *未序列*,并在未指定线程上运行。

对相同 volatile std::sig_atomic_t 类型对象的两次访问不会导致数据竞争,如果两者都发生在同一线程中,即使其中一个或多个发生在信号处理程序中。对于每个信号处理程序调用,由调用信号处理程序的线程执行的评估可以分为两组 A 和 B,这样 B 中的评估都不会 *先于* A 中的评估发生,并且这些 volatile std::sig_atomic_t 对象的评估取值就好像 A 中的所有评估都 先于 信号处理程序的执行发生,并且信号处理程序的执行 *先于* B 中的所有评估发生。

(C++14 起)

[编辑] 注意

POSIX 要求 `signal` 是线程安全的,并 指定了一系列可从任何信号处理程序调用的异步信号安全库函数。

信号处理程序预期具有 C 链接,并且通常只使用 C 和 C++ 公共子集中的功能。然而,常见的实现允许使用具有 C++ 链接的函数作为信号处理程序。

[编辑] 示例

运行此代码

#include

#include

namespace

{

volatile std::sig_atomic_t gSignalStatus;

}

void signal_handler(int signal)

{

gSignalStatus = signal;

}

int main()

{

// Install a signal handler

std::signal(SIGINT, signal_handler);

std::cout << "SignalValue: " << gSignalStatus << '\n';

std::cout << "Sending signal: " << SIGINT << '\n';

std::raise(SIGINT);

std::cout << "SignalValue: " << gSignalStatus << '\n';

}

可能的输出

SignalValue: 0

Sending signal: 2

SignalValue: 2

[编辑] 参考

C++23 标准 (ISO/IEC 14882:2024)

17.13.5 信号处理程序 [support.signal]

C++20 标准 (ISO/IEC 14882:2020)

17.13.5 信号处理程序 [support.signal]

C++17 标准 (ISO/IEC 14882:2017)

21.10.4 信号处理程序 [support.signal]

[编辑] 缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

缺陷报告

应用于

发布时的行为

正确的行为

LWG 3756

C++17

不清楚 std::atomic_flag 是否是信号安全的

它是

[编辑] 参见

raise

为特定信号运行信号处理程序 (函数) [编辑]

atomic_signal_fence(C++11)

线程与在同一线程中执行的信号处理程序之间的屏障 (函数) [编辑]

C 文档 关于 signal