报错storage size of ‘sa’ isn’t known,当使用std=c99编译struct sigaction

简介: 报错storage size of ‘sa’ isn’t known,当使用std=c99编译struct sigaction
void signal_exit_func(int signo)
{
    printf("exit signo is %d\n", signo);
    //CSingleton<CNet_TCPServer>::instance().stop_server();
}
void signal_exit_handler()
{
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = signal_exit_func;
    sigaction(SIGINT, &sa, NULL);//当按下ctrl+c时,它的效果就是发送SIGINT信号
    sigaction(SIGTERM, &sa, NULL);//kill pid
    sigaction(SIGQUIT, &sa, NULL);//ctrl+\代表退出SIGQUIT
    //SIGSTOP和SIGKILL信号是不可捕获的,所以下面两句话写了等于没有写
    sigaction(SIGKILL, &sa, NULL);//kill -9 pid
    sigaction(SIGSTOP, &sa, NULL);//ctrl+z代表停止
    //#define    SIGTERM        15
    //#define    SIGKILL        9
    //kill和kill -9,两个命令在linux中都有杀死进程的效果,然而两命令的执行过程却大有不同,在程序中如果用错了,可能会造成莫名其妙的现象。
    //执行kill pid命令,系统会发送一个SIGTERM信号给对应的程序。
    //执行kill -9 pid命令,系统给对应程序发送的信号是SIGKILL,即exit。exit信号不会被系统阻塞,所以kill -9能顺利杀掉进程。
}

本人编译报错:error: storage size of ‘sa’ isn’t known


    struct sigaction sa;


解决方法是:新添加头文件bits/sigaction.h即可。


#include <signal.h>

#include <bits/sigaction.h>




-----


参考文章:https://blog.csdn.net/gatieme/article/details/50991903


问题


今天在学习进程间通信之-信号signal–linux内核剖析(九)

遇见了一个奇怪的问题


storage size of ‘oldact’ isn’t known

1

1

于是FQ去google之。


分析了好久,终于发现问题的原因了。于是记录下来


发现


测试的代码如下


#include <stdio.h>

#include <stdlib.h>

#include <signal.h>

#include <bits/sigaction.h>

int main()

{

   struct sigaction act;

   return 0;



  • gcc test.c按照默认进行编译,无错误

image.png

  • gcc test.c -std=gnu99gcc test.c -std=gnu9x无错

image.png

  • gcc test.c -std=c99出错

image.png

  • gcc test.c --ansi出错

image.png

原因解析


参见 sigaction() and ANSI C

The following link has a lot of information.

https://www.securecoding.cert.org/confluence/display/seccode/SIG00-C.+Mask+signals+handled+by+noninterruptible+signal+handlers


其实说的很明晰了,就是说signal是一个ansi/C99编译器支持的函数,sigaction是后来在POSIX.1-2001中新增的接口,那么由于向前兼容的特性,ansi/c99并不支持sigaction函数接口。


也就是说,大多数操作系统均支持signal,但是却只有部分支持sigaction。


因此编译器在处理的时候,如果你指定了–ansi或者-std=c99的指令后,编译器会认为你要是编译一个标准的C程序,那么就在编译时(准确的来说是预处理阶段)将你不符合C标准的地方舍弃掉,


怎么舍弃呢?当然是通过宏了。


验证


我们知道gcc编译器可以通过-E来进行预处理来生成预处理后的文件。


那么我们现在来验证一下子,我们在生成的预处理文件中,搜索指定的sigaction关键字,看预处理的文件中,有没有该结构体的定义


gcc -E test.c -std=c99 | grep sigaction

gcc -E test.c --ansi | grep sigaction


image.png


很明显,我们指定了使用C标准的编译器后,编译器在预处理阶段针对非C标准的接口都屏蔽掉了。


同样我们使用GNU编译器扩展的C编译器进行预处理,看看有什么


gcc -E test.c -std=gnu99  | grep sigaction

gcc -E test.c -std=gnu9x  | grep sigaction

image.png



好了,我们现在是不是很清楚了


关于具体gcc编译参数的详情,请参见GCC Command-Line Options


image.png


我们可以看到–ansi指定使用古老的标准ansiC标准编译,-std=c99则指定使用新的C99标准编译,而gnu99 和gnu9x 则是gcc编译器对C99标准自己的实现


这些的关系是什么呢,


首先标准委员会指定了语言的标准,也就是ansi和后来的C88,C99标准


但是只有标准怎么行,必须有编译器来支持啊,于是各个编译器都开始逐步支持新的标准,同时也就是出现了-std=c89,-stdc99,为了兼容之前的程序,而保留旧的标准–ansi


但是对标准的支持,不可能一下子,只实现了一部分,慢慢再进行扩展,另外由于标准中某些地方可能并不实用,可能需要一些扩展,于是出现了-std=gnu99,现在很多编译器对C的语法都有一些不同的扩展,而这些扩展有些已经加入了新的标准中,有些并未加入或者正在议案加入。


解决


解决方法1


就是我们在编译的过程中编译器的类型,比如-std=gnu99


解决方法2


在#include <signal.h>之后显式添加sigaction的头文件


#include <bits/sigaction.h>  

1

1

这样编译器会显式的编译sigaction的定义


但是这种情况下需要注意,#include <bits/sigaction.h> 必须在#include <signal.h>之后


因为signal中会通过#error进行预处理,检查`bits/sigaction.h是否包含,

如果用户没有包含的话,预处理阶段就会报错


#error "Never include <bits/sigaction.h> directly; use <signal.h> instead."

image.png


版权声明:本文为博主原创文章 && 转载请著名出处 @ http://blog.csdn.net/gatiemehttps://blog.csdn.net/gatieme/article/details/50991903


相关文章
|
7月前
|
编译器
ofstream错误:error: variable ‘std::ofstream ofs’ has initializer but incomplete type
ofstream错误:error: variable ‘std::ofstream ofs’ has initializer but incomplete type
130 1
|
7月前
|
编译器 C++
offsetof宏的使用、模拟实现及 (size_t)&(((struct_type*)0)->mem_name)的解释
offsetof宏的使用、模拟实现及 (size_t)&(((struct_type*)0)->mem_name)的解释
|
关系型数据库 MySQL C++
类型收窄 error C2397: conversion from ‘const int‘ to ‘char‘ requires a narrowing conversion
类型收窄 error C2397: conversion from ‘const int‘ to ‘char‘ requires a narrowing conversion
202 0
relocation R_X86_64_PC32 against symbol ff_pw_9 can not be used when making a shared object
relocation R_X86_64_PC32 against symbol ff_pw_9 can not be used when making a shared object
293 0
|
Java Linux
LINUX编译OPENJDK:The tested number of bits in the target (0) differs from the number of bits expected
LINUX编译OPENJDK:The tested number of bits in the target (0) differs from the number of bits expected
227 0
解决办法:error LNK2005: "void * __cdecl operator new(unsigned int)" 已经在 LIBCMTD.lib(new.obj) 中定义
解决办法:error LNK2005: "void * __cdecl operator new(unsigned int)" 已经在 LIBCMTD.lib(new.obj) 中定义
287 0
|
C++
warning: non-static data member initializers only available with -std=c++11 or -std=gnu++11
warning: non-static data member initializers only available with -std=c++11 or -std=gnu++11
201 0
SAP WM 为Storage Type 004激活SUM报错 - Storage types without pick-point stor.type require partial pallet
SAP WM 为Storage Type 004激活SUM报错 - Storage types without pick-point stor.type require partial pallet
SAP WM 为Storage Type 004激活SUM报错 - Storage types without pick-point stor.type require partial pallet
解决办法:error LNK2005: &quot;void * __cdecl operator new(unsigned int)&quot; 已经在 LIBCMTD.lib(new.obj) 中定义
解决办法:error LNK2005: &quot;void * __cdecl operator new(unsigned int)&quot; 已经在 LIBCMTD.lib(new.obj) 中定义
222 0
成功解决absl.flags._exceptions.IllegalFlagValueError: flag --train_size=inf: Expect argument to be a str
成功解决absl.flags._exceptions.IllegalFlagValueError: flag --train_size=inf: Expect argument to be a str