2011-05-09 86 views
3

我有這個程序,爲什麼它會得到分段錯誤的任何想法?爲什麼分段錯誤?

#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': %s\n", 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("%d\n",i); 
     sleep(1); 
    } 
} 

void sig_handlerTimer1(int signum,siginfo_t* sf, void* au) 
{ 
    if(sf==NULL) 
    { 
     printf("sf is NULL\n"); 
     exit(1); 
    } 
    if((sf->si_value.sival_ptr)!=&timerid) //SEGV received here 
    { 
     printf("Stray signal\n"); 
    } 
    else { 
     int flag = 1; 
     printf("Caught signal: %d\n",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

回答

6

相差無幾從sigaction手冊頁,你應該有SA_SIGINFO標誌定義:

sa.sa_flags = SA_SIGINFO; 

否則,它不會用3個參數調用你的函數。不確定lt_sigaction在使用上有什麼不同。

+0

@ B.Mitch:謝謝,讓我試試。 – kingsmasher1 2011-05-09 13:33:51

+0

@ B.Mitch:哇!非常感謝你,謝謝..我很長時間以來一直在嘗試......它說,人們應該更仔細地閱讀手冊頁......謝謝你,上帝保佑你。 – kingsmasher1 2011-05-09 13:37:11

+0

這對我和所有程序員來說都是一個教訓,它顯示了仔細閱讀手冊頁的重要性。我們不能錯過任何事情,甚至一言不發。 – kingsmasher1 2011-05-09 13:39:13