为什么是分段错误

Why is the segmentation fault?

本文关键字:错误 分段 为什么      更新时间:2023-10-16

我有这个程序,知道为什么它会出错吗?

#include <stdlib.h>
#include <ctime>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <iostream>
#include <dlfcn.h>
#define LT_SIGACTION (*lt_sigaction) // For handle to actual sigaction in libc
static int (*lt_sigaction)(int, const struct sigaction*, struct sigaction*); // For sigaction wrapper
static void sig_handlerTimer1(int,siginfo_t*,void*);
timer_t timerid;
int main()
{
    int i;
    static struct sigaction sa;
    static struct sigevent sevp;  // argument to timer_create
    static struct itimerspec its; // argument to timer_gettime
    if(!lt_sigaction) {
        lt_sigaction = (int(*)(int, const struct sigaction*, struct sigaction*)) dlsym(RTLD_NEXT, "sigaction");
        if (!lt_sigaction) {
            fprintf(stderr, "Could not resolve 'sigaction' in 'libc.so': %sn", dlerror());
            exit(1);
        }
    }
    memset (&sevp, 0, sizeof (struct sigevent));
    sevp.sigev_value.sival_ptr = &timerid;
    sevp.sigev_notify = SIGEV_SIGNAL;
    sevp.sigev_notify_attributes = NULL;
    sevp.sigev_signo = SIGUSR1;
    /* Setting timer interval */
    its.it_interval.tv_sec = 0;
    its.it_interval.tv_nsec = 0;
    /* Setting timer expiration */
    its.it_value.tv_sec = 2;  // First expiry after 1 sec
    its.it_value.tv_nsec = 0;
    /* Setting the signal handlers before invoking timer*/
    sa.sa_sigaction = sig_handlerTimer1;
    sa.sa_flags = 0;
    LT_SIGACTION(SIGUSR1, &sa, NULL);
    // Even sigaction(SIGUSR1, &sa, NULL); gives SEGV
    if (timer_create(CLOCK_REALTIME, &sevp, &timerid) == -1)
    {
        fprintf(stderr, "LeakTracer (timer_trackStartTime): timer_create failed to create timer. " 
                "Leak measurement will be for entire duration of the execution period:%s n", strerror(errno));
        return 0;
    }
    if (timer_settime(timerid, 0, &its, NULL) == -1)
    {
        fprintf(stderr, "LeakTracer (timer_trackStartTime): timer_settime failed to set the timer. " 
                "Leak measurement will be for entire duration of execution period:%s n", strerror(errno));
        return 0;
    }
    for(i=0; i<10; i++)
    {
        printf("%dn",i);
        sleep(1);
    }
}
void sig_handlerTimer1(int signum,siginfo_t* sf, void* au)
{
    if(sf==NULL)
    {
        printf("sf is NULLn");
        exit(1);
    }
    if((sf->si_value.sival_ptr)!=&timerid) //SEGV received here
    {
        printf("Stray signaln");
    }
    else {
        int flag = 1;
        printf("Caught signal: %dn",signum);
        if (timer_delete(timerid) < 0)
        {
            fprintf(stderr, "timer deletion failed. " 
                    "This may result in some memory leaks (sig_handlerTimer1):%s n", strerror(errno));
        }
    }
}

以下是 GDB 回溯:

enter code here
Program received signal SIGUSR1, User defined signal 1.
0x00e52402 in __kernel_vsyscall ()
(gdb) s
Single stepping until exit from function __kernel_vsyscall, 
which has no line number information.
sig_handlerTimer1 (signum=10, sf=0x33, au=0x0) at signalTimer.cc:73
73      void sig_handlerTimer1(int signum,siginfo_t* sf, void* au)
(gdb) s

Breakpoint 1, sig_handlerTimer1 (signum=10, sf=0x33, au=0x0) at signalTimer.cc:75
75              if(sf==NULL)
(gdb) s
80              if((sf->si_value.sival_ptr)!=&timerid)
(gdb) s
Program received signal SIGSEGV, Segmentation fault.
0x08048a9f in sig_handlerTimer1 (signum=10, sf=0x33, au=0x0) at signalTimer.cc:80
80              if((sf->si_value.sival_ptr)!=&timerid)
(gdb) bt
#0  0x08048a9f in sig_handlerTimer1 (signum=10, sf=0x33, au=0x0) at signalTimer.cc:80
#1  <signal handler called>
#2  0x00e52402 in __kernel_vsyscall ()
#3  0x00724970 in __nanosleep_nocancel () from /lib/libc.so.6
#4  0x007247bf in sleep () from /lib/libc.so.6
#5  0x08048a5a in main () at signalTimer.cc:69
(gdb) q
The program is running.  Exit anyway? (y or n) y 

这是一个C++代码,使用 g++ 编译,尽管与 C 几乎没有区别

sigaction手册页中,您应该定义SA_SIGINFO标志:

sa.sa_flags = SA_SIGINFO;

否则,它不会使用 3 个参数调用您的函数。 不确定lt_sigaction用法是否有任何差异。