2016-05-09 12 views
-1

Cプログラムでチャットインターフェイスを作成しようとしています。 プログラムは2つのFIFOを使用して、cat fifo_outtee fifo_in > /dev/nullというコマンドを同時に実行する分岐したxtermと通信します。 その後、他のスレッドがfifo_outにメッセージを出力すると同時に、ターミナルから来る* fifo_in の入力を読み取るスレッドが開かれ、xtermに表示されます。cat、tee、fifoを使用したマルチスレッドCプログラムでのxtermからの印刷と読み取り

すべてはうまくいくようです...端末にテキストを書き込んでいる間にメッセージが印刷された場合を除き、入力されたテキストを2つの部分に分割します。これはセグメンテーションを引き起こします!

あなたはそれがどうして起こるのか考えていますか?

int open_terminal(pid_t *pid, int *pipe) 
{ 
    mkfifo("fifo_in", 0600); 
    mkfifo("fifo_out", 0600); 
    pid_t p = fork(); 
    int fd_in, fd_out; 
    switch (p) { 
    case -1: 
     return -1; 
    case 0: 
     execlp("xterm", "xterm", "-e", "cat fifo_out & tee fifo_in > /dev/null", NULL); 
     exit(EXIT_FAILURE); 
     break; 
    default: 
     if ((fd_in = open("fifo_in", O_RDONLY)) == - 1) 
      return -1; 
     if ((fd_out = open("fifo_out", O_WRONLY)) == - 1) 
      return -1; 
     *pid = p; 
     pipe[0] = fd_in; pipe[1] = fd_out; 
     return 0; 
    } 
    return -1; 
} 


void *message_thread(void *args) 
{ 
    int *fd_out = (int *)args; 
    while (1) { 
    dprintf(*fd_out, "You're awesome!\n"); 
    sleep(5); 
    } 
} 


void *input_thread(void *args) 
{ 
    int *fd_in = (int *)args; 
    FILE *f = fdopen(*fd_in, "r"); 
    while (1) { 
    size_t n; 
    char *line; 
    getline(&line, &n, f); 
    printf("Read: %s", line); 
    free(line); 
    if(strcmp(line, "exit\n") == 0) 
     return NULL; 
    } 
} 


int main(int argc, char *argv[]) 
{ 
    pid_t pid; 
    int pipe[2]; 
    if (open_terminal(&pid, pipe) == -1) { 
    printf("Can't open terminal.\n"); 
    return 1; 
    } 
    pthread_t mt, it; 
    pthread_create(&mt, NULL, message_thread, &pipe[1]); 
    pthread_create(&it, NULL, input_thread, &pipe[0]); 

    pthread_join(it, NULL); 

    return 0; 
} 

、私の状況を再現するプログラム入力にいくつかのテキストを実行して、あなたのテキストを再度入力し、入力した後、いくつかのテキストが印刷されるまで待機する:ここで

は、最小限の例です。

free(line); 
if(strcmp(line, "exit\n") == 0) 

まずあなたは、あなたはすぐにそのメモリを使用して、メモリが割り当てられて解放し、lineで指さ:input_thread機能から

+0

プログラムを終了するときに 'unlink'コマンドを使ってFIFOをクリーンアップすることもできます。違いがある場合は、 'getline'の入力から' '\ n ''の後にトリミングすることもできます。 'getline'は読み込んだ文字数(' '\ n''を含む)を返すので、単純に戻り値を使うことができます(例えば 'nchr = getline(...'と 'line [ - nchr] = 0; '' \ n ''を削除してください。strcmp(行、終了\ n")のような不思議なテストは必要ありません。 –

答えて

1

。これにより、の未定義の動作が発生します。

そして、それがすべてではありません、あなたはgetline機能に初期化されていないポインタとサイズを渡すために初期化されていないローカル変数は不定値を持っているので、それが実際にメモリを割り当てません(それは非常に可能性が一見ランダムではなくなり、ゼロまたはNULL)。明示的に変数をゼロに初期化し、NULLとすると、getline関数は必要なメモリを割り当てます。初期化以外の何かに初期化されていないローカル(静的ではない)変数を使用すると、未定義の動作につながります。

おそらく、クラッシュの原因となる一見ランダムなメモリへの書き込みは、getlineという未定義の動作です。

+0

おっと、 'free'は適切な場所にありません。実際のプログラムではそうではありません。実際の理由は、もう一つは、初期化されていない 'size_t'です。ありがとう。 –

関連する問題