2017-02-09 164 views
0

シグナルハンドラを実装しようとしますが、警告の受信:互換性のないポインタ型からの代入 - 修正する方法?

assignment from incompatible pointer type [enabled by default] 
    act.sa_sigaction = sigChldHandler; 

は...また、私の教授は指摘しました。

char * argv[3]; 
argv[0]= GUESSER_PROGNAME; 
argv[2]= NULL; 

これは3つのchar型のポインタVARSにメモリを割り当て、彼らはどこにも特に指していない。」しかし、私は彼がそれによって何を意味するのかわからない。

ファイル\ 1

#include "assign2Headers.h" 
pid_t answererPid; 
pid_t guesserPid; 

int shouldRun = 1; 

void sigAlrmHandler(int sig) 
{ 
    kill(answererPid,TIME_OVER_SIGNAL); 
    kill(guesserPid,TIME_OVER_SIGNAL); 
    shouldRun=0; 
} 

void sigChldHandler(int sig) 
{ 
wait(NULL); 
shouldRun=0; 
} 

int main(void){ 


    struct sigaction act; 
    memset(&act, '\0', sizeof(struct sigaction)); 

    act.sa_handler = sigAlrmHandler; 
    sigaction(SIGALRM, &act, NULL); 

    act.sa_sigaction = sighldHandler; 
    sigaction(SIGCHLD, &act, NULL); 


char line[LINE_LEN]; 
char * argv[3]; 
argv[0]= GUESSER_PROGNAME; 
argv[2]= NULL; 
answererPid = fork(); 

if(answererPid == 0){ 

     execl(ANSWERER_PROGNAME,ANSWERER_PROGNAME,(char*)NULL); 

    } 

else{ 
     sleep(1); 
     snprintf(line,LINE_LEN,"%d",answererPid); 
     guesserPid=fork(); 
     if(guesserPid==0) 
     { 
      execl(GUESSER_PROGNAME,GUESSER_PROGNAME,argv[0],line,(char*)NULL); 
     } 
     else 
     { alarm(NUM_SECONDS); 
      while(shouldRun) 
       sleep(1); 
      sleep(1); 
      sleep(1); 
      printf("launcher finished\n"); 
      return (EXIT_SUCCESS); 

     } 

    } 

} 

\ファイル2

#include "assign2Headers.h" 

int shouldRun = 1; 

void timeoverhandler(int sig) 
{ sleep(1); 
    printf("\nOh no! The time is up!\n"); 
    printf("guesser finished\n"); 
    shouldRun=0; 
    exit(EXIT_SUCCESS); 
} 

void winsignalhandler(int sig) 
{ 
    printf("\nCongratulations! You found it!\n"); 
    shouldRun=0; 
     signal(WIN_SIGNAL,winsignalhandler); 
} 

void correctsignalhandler(int sig) 
{ 
    printf("Yay! That was right!\n"); 
    signal(CORRECT_SIGNAL,correctsignalhandler); 
} 

void incorrectsignalhandler(int sig) 
{ 
    printf("Oops! That was wrong. Please restart from the beginning.\n" 
"\nRe-starting from the beginning:\n"); 
    signal(INCORRECT_SIGNAL,incorrectsignalhandler); 
} 

int main(int argc,char* argv[]) 
{ 

    pid_t answererPid=atoi(argv[1]); 
    signal(TIME_OVER_SIGNAL,timeoverhandler); 
    signal(WIN_SIGNAL,winsignalhandler); 
    signal(CORRECT_SIGNAL,correctsignalhandler); 
    signal(INCORRECT_SIGNAL,incorrectsignalhandler); 

    while(shouldRun) 
    { int guess; 
     printf("What would you like your next guess to be: 0 or 1? "); 
     scanf("%d",&guess); 
     if(guess==0) 
      kill(answererPid,ZERO_SIGNAL); 
     if(guess==1) 
      kill(answererPid,ONE_SIGNAL); 
     sleep(2); 

    } 


    printf("guesser finished\n"); 
    return (EXIT_SUCCESS); 


} 

ファイル3

\ファイル\
//---  Common standard header files    ---// 

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <signal.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <unistd.h> 

////---  Common constants:     ---// 

#define  ZERO_SIGNAL  SIGUSR1  
#define  ONE_SIGNAL  SIGUSR2 
#define  CORRECT_SIGNAL  SIGUSR1 
#define  INCORRECT_SIGNAL SIGUSR2 
#define  WIN_SIGNAL  SIGINT 
#define  TIME_OVER_SIGNAL SIGTERM 

#define  GUESSER_PROGNAME "guesser" 
#define  ANSWERER_PROGNAME "answerer" 

#define  LINE_LEN  256 
#define  NUM_SECONDS  30 
//---  Inclusion of header files    ---// 

#include "assign2Headers.h" 

//---  Definition of constants:    ---// 

#define  PATTERN_LEN 4 

//---  Definition of global vars:    ---// 

int  answer; 
int  numCorrect = 0; 
int  shouldRun = 1; 


//---  Definition of global fncs:    ---// 

void  timeUpHandler (int  sig 
       ) 
{ 
    shouldRun = 0; 
} 


void  guessHandler (int  sig, 
       siginfo_t* infoPtr, 
       void*  dataPtr 
       ) 
{ 
    int toSendBack; 
    int userBit  = (sig == ONE_SIGNAL); 
    int correctBit = ((answer >> numCorrect) & 0x1); 
    int isCorrect = (correctBit == userBit); 

    printf("position %d: userBit %d, correctBit %d\n", 
    numCorrect,userBit,correctBit 
    ); 

    if (isCorrect) 
    { 
    numCorrect++; 

    if (numCorrect >= PATTERN_LEN) 
     toSendBack = WIN_SIGNAL; 
    else 
     toSendBack = CORRECT_SIGNAL; 
    } 
    else 
    { 
    numCorrect = 0; 
    toSendBack = INCORRECT_SIGNAL; 
    } 

    kill(infoPtr->si_pid,toSendBack); 
} 


int  main  (int argc, 
       char* argv[] 
       ) 
{ 
    // I. Application validity check: 

    // II. Run program: 
    // II.A. Initialize random number generator and choice: 
    srand(getpid()); 

    answer = rand() % (1 << PATTERN_LEN); 

printf("(The answer is %d)\n",answer); 

    // II.B. Install signal handlers: 
    struct sigaction act; 

    memset(&act,'\0',sizeof(act)); 
    act.sa_handler = timeUpHandler; 
    sigaction(TIME_OVER_SIGNAL,&act,NULL); 

    act.sa_flags  = SA_SIGINFO; 
    act.sa_sigaction = guessHandler; 
    sigaction(ZERO_SIGNAL,&act,NULL); 
    sigaction(ONE_SIGNAL,&act,NULL); 

    // II.C. Hand out while game still active: 
    while ((numCorrect < PATTERN_LEN) && shouldRun) 
    sleep(1); 

    // III. Finished, return answer: 
    printf("answerer finished\n"); 
    return(EXIT_SUCCESS); 
} 

どのように私はこの警告を削除するには、彼がそれによって何を意味するのでしょうか?誰かが私を助けてください。

+0

'のchar *のARGV [3]。 argv [0] = GUESSER_PROGNAME; argv [2] = NULL; 'なぜ文字列をポインタの配列に入れるのか理解できません。 – minigeek

+0

@RoadRunnerええ!代わりにmallocステートメントが必要なのでしょうか? – minigeek

答えて

3

あなたはLinuxで作業していると思います。 sa_sigactionと一致しないvoid sigChldHandler(int sig)

struct sigaction { 
     void  (*sa_handler)(int); 
     void  (*sa_sigaction)(int, siginfo_t *, void *); 
     sigset_t sa_mask; 
     int  sa_flags; 
     void  (*sa_restorer)(void); 
    }; 

プロトタイプ:sigaction manページから。したがって警告。

あなたは、シグナルハンドラ関数を設定したりSIG_IGN/SIG_DFLアクションを指定する

  1. sa_handlerを使用することができます。
  2. sa_sigactionシグナルハンドラ関数を設定する - ユーザは、ユーザのコンテキストとsiginfo構造(センダプロセスの詳細、信号の種類など)のような詳細にアクセスする必要がある場合。この用途ではsa_flagsSA_SIGINFOを設定する必要があります。

あなたの場合、sa_handlerで十分です。 main()

:また

struct sigaction act; 
act.sa_handler = sigChldHandler; 
act.sa_flags = SA_RESTART; 
sigaction(SIGCHLD, &act, NULL); 

、あなたは彼らのために同じハンドラを使用する場合に限り設定したい信号あたり

  1. 利用別々sigaction構造。
  2. sigaction() & signal()用法を混在させないでください。 1つにこだわる。 sigactionそれは新機能としてたぶん、&はsignal()よりも多くの機能を提供します。
+1

今後の訪問先のメンバーに役立つように、回答の中でそれを(それに置き換えて)変更する方法を示してください。 – minigeek

+0

私は次のように置き換えます。{struct sigaction act; memset(&act、 '\ 0'、sizeof(struct sigaction)); act.sa_handler = sigAlrmHandler; sigaction(SIGALRM、&act、NULL);}と{struct sigaction act; act.sa_handler = sigAlrmHandler; act.sa_flags = SA_RESTART; sigaction(SIGALRM、&act、NULL);}} ..? –

+0

扱う信号ごとに、私が言及したように4本のラインを追加します。それぞれの信号に対して、別々のsigaction構造変数(act1、act2 ...など)を使用する必要があります。 – ReddyVeeru

1

このセグメントは:

char * argv[3]; 
argv[0]= GUESSER_PROGNAME; 
argv[2]= NULL; 

argv[0]には無効です。 argvはポインタの配列なので、ポインタを使用する前にそれらのポインタがどこかを指していることを確認する必要があります。

これはstrdup()で達成することができます:

argv[0]= strdup(GUESSER_PROGNAME); 

それともmalloc()/strcpy()と:

argv[0]= malloc(strlen(GUESSER_PROGNAME)+1); 
strcpy(argv[0], GUESSER_PROGNAME); 

注:malloc()も、それが失敗した場合にNULLを返すことができ、チェックする必要があります。ヒープ上に割り当てられたメモリは、最後にfree() 'となるはずです。

明確さの面では

、あなたは置き換えることができます:

#define GUESSER_PROGNAME "guesser" 

で:

const char *guesser_progname = "guesser"; 
+0

@ J.Doeなぜこの投稿からすべてのコードを削除しようとしていましたか?投稿したコードから、これらの推奨事項が役立ちます。 – RoadRunner

+1

"*' argv [0] '*には無効です:" #define GUESSER_PROGNAME "...."と仮定すると.... "' 'char * argv [3]; argv [0] = GUESSER_PROGNAME; 'は完全に有効です。 'argv [1]'の妥当性を参照することを意味しましたか? – alk

+0

@alkはい、あなたは正しいです、そのOPは彼のコードの多くが変更されて以来、私はこの答えは現時点では技術的に間違っていると思います。私は何を考えているのか分からず、ポインタに定数文字列を設定すると問題ありません。 – RoadRunner

関連する問題