为什么用memset()初始化sigint变量有助于防止Seg Faults?

时间:2016-09-15 01:46:35

标签: c++ c struct

背景

struct sigaction用于为处理中断的小型C程序设置处理程序。当我收到" Segmentation fault(core dumped)"完成第二个处理程序的实现后的错误消息。我以完全相同的方式设置两个处理程序。第一个中断处理程序工作正常而没有初始化sigaction结构,但是,当我完成第二个处理程序的实现时,我收到了seg错误。

问题:

为什么用memset()初始化sigaction结构有助于修复错误?

CODE:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <signal.h>
#include <string.h>

#define ALARMSECONDS    3
int numSigints = 5;

/* Handler function that prints out the current time on a SIGALRM interrupt. */
static void hdl(int signum)
{
    time_t currTime;
    time(&currTime);
    printf("\ncurrent time is %s", ctime(&currTime));
    alarm(ALARMSECONDS);//re-arm the alarm

}

/* Handler function that captures SIGINT interrupts 5 times before 
   actually exiting. Makes use of global variable to keep track of
   number of times the interrupt was sent.
 */
static void sigint_hdl(int signum)
{

    numSigints -= 1;    

    if(numSigints == 0)
    {
      printf("\nFinal Control-c caught. Exiting.\n");
      exit(1);
    } 
    else
    {
      printf("\nControl-c caught. %d more before program is ended.\n", 
        numSigints);
    }   
}

/* Periodically prints out the current time in Unix date format using 
   sigaction interrupt handling.   
*/
int main(int argc, char *argv[])
{

    //
    // vars
    //
    struct sigaction act;
    struct sigaction sigint_act;

    memset(&act, '\0', sizeof(act));//TODO Why does this fix SEGFAULT???

    //
    // intro
    //
    printf("Date will be printed every 3 seconds.\n");
    printf("Enter ^C 5 times to end the program.\n");

    //
    // set alarm to go off in 3 seconds
    //
    alarm(ALARMSECONDS);

    //
    // set handler of the sigaction to 'hdl' function defined above
    //
    act.sa_handler = hdl;
    sigint_act.sa_handler = sigint_hdl;

    //
    // activate sigaction
    //
    if(sigaction(SIGALRM, &act, NULL) < 0)
    {
      perror("sigaction -- SIGALRM");
      return 1;
    }

    if(sigaction(SIGINT, &sigint_act, NULL) < 0)
    {
      perror("sigaction -- SIGINT");
      return 1;
    }

    //
    // infinite loop
    //
    while(1) {
    }

    return 0;
}

1 个答案:

答案 0 :(得分:3)

sigaction结构中有许多字段。将它们全部设为零会将它们设置为默认值。

如果它们不是零,它们将以系统调用文档中描述的任何方式进行解释。一个示例是两个字段sa_masksa_sigaction。并且根据sa_mask的值,将调用sa_sigaction处理程序而不是您的代码安装的预期信号处理程序。并且由于你没有初始化指针,它将有一些垃圾值,并且将尝试不仅仅取消引用,而是通过垃圾指针调用函数。

因此,如果您未能初始化结构,则会得到未定义的行为。有时它会起作用,有时它不会以神秘的方式发生,例如崩溃。

通过将整个结构清除为零,您可以确保将发生默认行为,并通过它们对结构所做的任何非默认设置进行修改。

获得的经验教训:始终清除并初始化传递给库函数的所有结构。