分段故障(核心转储)-gaz站示例

时间:2016-05-14 20:17:16

标签: c

当我运行此代码时,请任何人帮助我 我得到分段错误(核心转储) 这是一个gaz站问题的程序我想同步来到车站的汽车类型和我使用共享的mameory并保存一些变量同步但是当我运行程序时显示我的分段故障我在fedora 13中运行它     `

//tmp* global=null;
int i=1;
//define struct for save it shared memory segment
typedef struct{
    int emergen ;
    int truck ;
    int type;
    char car[20];
    int gaz;
    int pid;
}tmp;

tmp * global;
//emergency car handler
void emergency(int sig);

//handler of truck and normal car 
void normal(int sig);

void main()
{
    printf("hello I'm gaz station");
    tmp* shared_memory;
    key_t k = ftok("/tmp",'a');
    //allocate shared memory
    const int shared_segment_size = 0x6400;
    //allocate shared memory
    int seg_id=shmget(k,shared_segment_size,IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH );
    //attach to shared memory
    shared_memory = (tmp*) shmat (seg_id, 0, 0);
    //write to shared memory
    //memccpy(shared_memory,&tmp,sizeof(tmp));
    //some vars i used as semaphore for syncronize other process
    global=shared_memory;
    global->emergen=1;
    global->truck=1;
    global->pid=getpid();
    //define mask for signal handler
    sigset_t newsigset;
    sigemptyset(&newsigset);
    sigfillset(&newsigset);
    sigdelset(&newsigset,SIGINT);
    sigdelset(&newsigset,SIGUSR1);
    sigdelset(&newsigset,SIGQUIT);

    //handle the signals
    if(sigprocmask(SIG_BLOCK,&newsigset,NULL)<0)
    {
        printf("ann error in sigprocmask \n");
    }

    //sigactiion function
    struct sigaction act;
    sigemptyset(&act.sa_mask);
    sigfillset(&act.sa_mask);
    act.sa_handler=emergency;
    if(sigaction(SIGINT,&act,NULL))
    {
        printf("couldn't execute sigaction for SIGINT signal \n");
    }



    //sigaction for SIGQUIT  SIGUSR1
    struct sigaction act1;//define struct for sigaction
    act1.sa_handler=normal;
    act1.sa_flags=SA_NODEFER;
    sigemptyset(&act1.sa_mask);
    if(sigaction(SIGUSR1,&act1,NULL)==-1)
    {
        printf("error in sigaction for SIGUSR1  SIGUSR1 \n");
    }
    if(sigaction(SIGQUIT,&act1,NULL)==-1)
    {
        printf("error in sigaction for SIGQUIT  SIGUSR1 \n");
    }
    while(1)
        ;

}
//handler for type of car
void emergency(int sig)
{   
    printf("*****************************************\n");
    printf("i'm emergency car ...... and my name %s",global->car);

    //char[20] name;
    //printf("please enter the name of the car \n");
    //scanf("%s \n",name);
    //strcpy(global.car,name);
    sleep(1.5);
    printf("emergency car that called %s finish",global->car);//print for user
    printf("%d remain in the station \n",global->gaz);
    printf("*****************************************\n");  
}




//handler of truck and normal car 
void normal(int sig)
{
    if(i!=1)
    {printf("interrupt has been occured \n");}
    printf("*****************************************\n");
    i=0;
    if(sig==SIGUSR1)
    {
        printf("I'm truck \n");
        printf("my name is %s \n",global->car);
        sleep(1.5);
        //type of car that come to gaz station
        if(global->type==1)
        {
            printf("truck %s finish support the station \n",global->car);
                //printf("*****************************************\n");
        }
        else if(global->type==2)
        {
            printf("truck %s finish the process \n",global->car);
        }
        sleep(1.5); 
        printf("%d remain in the station \n",global->gaz);
        printf("*****************************************\n");  

    }
    else if(sig==SIGQUIT)
    {
        printf("I'm normal car my name is %s \n",global->car);
        sleep(1.5);
        printf("car finish \n");
        printf("*****************************************\n");
    }
    i=1;
}    `

1 个答案:

答案 0 :(得分:0)

使用信号比它的声音复杂得多,因此你应该只将它们用于它们的目的:捕获一个事件(通常是一个系统事件)并尽可能地做一些事情,比如通过写一个字节来解锁一个消费者线程打开的管道或使用sem_post

程序的正常执行在信号的任何地方都会中断。 当您在信号中调用printf时,用于根据给定参数构建字符串的printf内部静态变量会被更改。 如果在发出信号时,程序的正常执行位于printf调用内,则信号陷阱会破坏内部静态变量,printf调用将无法恢复。这同样适用于许多标准函数,例如strerror

This opengroup link为您提供信号陷阱中已接受的标准函数调用的详尽列表。你可以看到不应该使用printf(奇怪的是sleep可以)。

但是,由于程序的正常执行是一个简单的空循环, 这不应该是我猜的问题。但是您的全局变量很有意义:

  • 未完全初始化(特别是其car数组可能不包含任何\0
  • 它托管在共享内存段

如果在完全初始化此global变量之前调用了陷阱, 或者当另一个过程正在改变它时,那么你的程序可能会行为不端。如果其他进程正在使用共享的global变量,而此变量正在改变它,则同样适用。共享内存访问应始终使用系统互斥或原子更新进行保护,但从信号陷阱(sem_wait调用)内部获取互斥锁是不行的。因此,你的程序设计对我来说是错误的。