storage size of ‘oldact’ isn’t known

#include <signal.h>

int main()
{
struct sigaction act, oldact;
return 0;
}


dies with the message


testgcc4.c: In function ‘main’:
testgcc4.c:6: error: storage size of ‘act’ isn’t known
testgcc4.c:6: error: storage size of ‘oldact’ isn’t known


if I use -std=c99 or --ansi?
gcc testgcc4.c compiles without problem but adding -std=c99 or --ansi produces
the error message above (for any of gcc-3.4, gcc-4.0, gcc-4.1) but neither

icc nor gcc on FreeBSD has a problem with -std=c99 or --ansi


Sumarry:

use -std=gnu99 on linux if you need some C99 functions (e.g. strtof) but also want to use functions like sigaction and strtok_r

gcc on linux is stricter than gcc on FreeBSD (or icc on either FreeBSD or linux) concerning standards.
gcc -std=c99 on linux means: *only* recognize functions specified in the standard (no sigaction, no strtok_r etc)
gcc -std=c99 on FreeBSD or icc -std=c99 on either FreeBSD or linux means recognize functions specified in the standard. This corresponds more or less to -std=gnu99 on linux

PS. This trap seems to be quite common (e.g. discussions on debian-glibc about the "fact" that strtof is completely broken on linux). I would be grateful if somebody could point me to a good overview describing what standards compliance means for various OS/compiler+options/standards combinations.

### 关于 `sigaction` 函数和信号处理程序的实现问题 在 C 语言中,`sigaction` 是用于注册信号处理函数的重要接口。它允许开发者指定当特定信号发生时应采取的操作。如果存在多个信号处理函数(如 `funcA` 和 `funcB`),则需要特别注意它们的行为以及可能引发的问题。 #### 1. **信号处理函数的竞争条件** 如果两个不同的信号分别由 `funcA` 和 `funcB` 处理,并且这两个信号可能会在同一时间触发,则可能存在竞争条件。这是因为信号处理函数通常是异步执行的,即它们可以在任意时刻中断主线程或其他线程的运行[^1]。为了避免这种潜在的风险,可以考虑以下方法: - 使用 `pthread_sigmask` 或者 `sigprocmask` 来屏蔽某些信号,直到当前正在处理的信号完成为止。 - 确保信号处理函数尽可能短小精悍,仅执行必要的操作,比如记录日志或者设置全局标志位。 #### 2. **信号安全函数的选择** 并非所有的标准库函数都可以在信号处理函数中安全地调用。例如,`printf` 被认为是非信号安全的,因为它不是重新进入安全的(reentrant-safe)。因此,在设计 `funcA` 和 `funcB` 的时候,应该避免使用这些不安全的函数。替代方案包括: - 使用 `write` 系统调用来代替 `printf` 进行简单的调试输出[^3]。 - 如果确实需要复杂的日志功能,可以通过预先分配好的缓冲区来存储数据,并延迟到非信号上下文中再进行实际的日志写入。 #### 3. **恢复原始信号行为** 有时为了兼容性或者其他原因,我们需要保存原有的信号处理逻辑并在新的处理完成后还原它。这可以通过保存旧的 `struct sigaction` 结构体实例实现。具体做法如下所示: ```c #include <signal.h> #include <stdio.h> void funcA(int signum); void funcB(int signum); int main() { struct sigaction sa, old_sa; // 设置 funcA 作为 SIGUSR1 的新动作 sa.sa_handler = funcA; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGUSR1, &sa, &old_sa); // 后续代码... // 恢复原来的 SIGUSR1 动作 sigaction(SIGUSR1, &old_sa, NULL); return 0; } void funcA(int signum) { printf("Caught signal %d\n", signum); } ``` 上述例子展示了如何安装一个新的信号处理器 (`funcA`) 并保留之前的配置以便稍后恢复[^2]。 #### 4. **堆栈溢出风险** 默认情况下,大多数操作系统会给每个进程提供一个小而固定的信号处理专用堆栈区域 (称为 alternate signal stack),但如果信号频繁到来或单次处理耗时过长,则可能导致此空间不足从而造成崩溃。解决办法之一就是显式创建更大的备用堆栈供复杂信号处理场景使用: ```c #include <signal.h> #include <stdlib.h> char altstack[SIGSTKSZ]; void setup_alt_stack() { stack_t ss; ss.ss_sp = altstack; ss.ss_size = sizeof(altstack); ss.ss_flags = 0; if (sigaltstack(&ss, NULL) != 0) perror("sigaltstack"); } ``` 调用以上函数即可切换至自定义的大容量堆栈环境下去应对那些较为繁重的任务型信号事件处理需求。 --- ### 问题
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值