2012-03-30 9 views
0

入力ファイルを取得し、含まれている項目をスレッドで画面に出力するプログラムを作成しようとしています。しかし、最後のスレッドは予期せず出力を出すことはありません。私は問題が何であるか把握できませんでした。私はあなたの助けを待っています。PthreadがC言語で突然実行する

各スレッドは、inputFile1、inputFile2、およびtargetBufという3つのパラメータを取得します(シーケンス番号といいます)。ファイルはソートされていますが、単にそのユニオンを順番に印刷しようとしています。正の数だけが印刷されます。

コマンドライン:マージN outfile file1 file2 file3 .... fileN Nは入力ファイルの数です。

2つの入力ファイル(1つのスレッドを意味します)を指定すると動作します。私が4つのファイルを与えた場合、第1スレッドは出力を出し、第2スレッドは出力しません。 6つの入力ファイルを与えると、1番目と2番目のスレッドは出力しますが、3番目のスレッドは出力しません。

ヘッダファイルには2つの構造体があります。私はそれらを下に貼り付けた。

//thread information 
struct threadInfo{ 
    pthread_t tid; 
    pthread_attr_t attr; 
}; 
//Beginning thread input 
struct beginThreadInput{ 
    FILE **inputFile1, **inputFile2; 
    int targetBuf; 
}; 
typedef struct threadInfo THREADINFO; 
typedef struct beginThreadInput BEGINT_INPUT; 

メインファイルコード:

 #include <stdio.h> 
     #include <unistd.h> 
     #include <stdlib.h> 
     #include <pthread.h> 
     #include <semaphore.h> 
     #include <sys/types.h> 
     #include <errno.h> 
     #include <sys/mman.h> 
     #include <sys/stat.h> 
     #include <unistd.h> 
     #include <fcntl.h> //for O_ constants 
     #include <sys/stat.h> 
     #include <pthread.h> /* thread library */ 

     #include "merge.h" 



     int main(int argc, char** argv){ 
     int i, k, N; 

     /***FILE INITIALIZATION***/ 
     FILE *output; 
     N = atoi(argv[1]); 
     output = fopen(argv[2], "w"); 
     FILE **inputFileList = ((FILE**)malloc (N * sizeof(FILE*))); 
     printf("int N is %d\n", N); 
     for(i = 0; i<N; i++){ 
      inputFileList[i] = fopen(argv[i + 3], "r"); 
     } 
     //START THREADS 
     BEGINT_INPUT **threadInputList = ((BEGINT_INPUT**) malloc ((N/2)*  sizeof(BEGINT_INPUT*))); 
     THREADINFO **threadInfoList = ((THREADINFO**) malloc ((N/2) *   sizeof(THREADINFO*))); 
     for(i = 0; i< N/2 ; i++){ 
      threadInputList[i] = (BEGINT_INPUT *) malloc (sizeof(BEGINT_INPUT)); 
      threadInfoList[i] = (THREADINFO *) malloc (sizeof(THREADINFO)); 
     } 
     pthread_t tid; 
     pthread_attr_t attr; 
     for(i = 0, k = 0; i < (N/2); i++){ 


      threadInputList[i]->inputFile1 = &(inputFileList[k]); 
      threadInputList[i]->inputFile2 = &(inputFileList[++k]); 
      threadInputList[i]->targetBuf = i; 
      pthread_attr_init(&(threadInfoList[i]->attr)); 
      pthread_create(&(threadInfoList[i]->tid), &(threadInfoList[i]->attr), runBeginningThreads, (void*)threadInputList[i]); 

     } 
     pthread_join((threadInfoList[[(N/2)-1]]->tid), NULL); 
     for(i = 0; i<N; i++){ 
      fclose(inputFileList[i]); 
     } 

     } 

     void *runBeginningThreads(void *input){ 

     BEGINT_INPUT *myInput = (BEGINT_INPUT *)input; 
     int first = -1, second = -1, iseof; 
     printf("Thread number %d\n", myInput->targetBuf); 
     while((second > -2) && (first > -2)){ 
      //read integer values from files 
      if(first == -1){ 
       iseof = fscanf(*(myInput->inputFile1), "%d", &first); 
       if(iseof == EOF){ 
        first = -2;  //means end of file 
       } 
       else if(first < 0) 
        first = -1;  //means waiting for an integer 
      } 
      if(second == -1){ 
       iseof = fscanf(*(myInput->inputFile2), "%d", &second); 
       if(iseof == EOF){ 
        second = -2; 
       } 
       else if(second < 0) 
        second = -1; 
      } 
      //print smaller one 
      if((first != -1) && (second != -1)){ 
       if(((first < second) || (second == -2)) && (first != -2)){ 
        printf("%d\n", first); 
        first = -1; 
       } 
       else if(second != -2){ 
        printf("%d\n", second); 
        second = -1; 
       } 
      } 
     } 
     } 

答えて

0

私は、次のように私の質問を解決:ここ

は余分へのポインタのポインタ何も必要ありません使用していない、少し簡単なバージョンです。上記のように、私はmain関数でファイルを開いて、それを対応するスレッドに渡します。私はこのように変更して、ファイルの名前をスレッドに渡し、その中の関連するファイルを開きます。このラインは、ループ内で実行されている

threadInputList[i]->inputFile1 = &(inputFileList[k]); 
threadInputList[i]->inputFile2 = &(inputFileList[++k]); 

の下

はまた、ファイルを渡しながら、私はミスをした、そのコードがあります。これは、kを1つだけ増やすので、次のような入力シーケンスを引き起こします([0,1]、[1,2]、[2,3]、[3,4] ...)。ただし、 inputFilesの正しいコードは次のとおりです。

threadInputList[i]->inputFile1 = &(inputFileList[k++]); 
threadInputList[i]->inputFile2 = &(inputFileList[k++]); 

問題を指摘します。私はファイル名のためにこのコードを修正しました、それがそこに掲示されるのでFILEポインタ変数ではありません。しかし、それを明確にするため、そこに掲載されたコードにバグを修正しました。あなたの助けをありがとう、皆さん

2

主な問題は、すべてのファイルを閉じてから、プログラムを終了する前に、あなただけの仕上がりに一つのスレッドを待つことになるかもしれません。

あなたのプログラムには他にもいくつかの複雑な問題がありますが、これはおそらく単純化することができます。私はあなたが本当にそれを必要としないときに余分なポインタの間接参照を使用することを意味します。

struct beginThreadInput{ 
    FILE *inputFile1, *inputFile2; 
    int targetBuf; 
}; 

/* ... */ 

int main(int argc, char** argv){ 
    /* ... */ 

    BEGINT_INPUT *threadInputList = malloc ((N/2)*  sizeof(BEGINT_INPUT)); 
    THREADINFO *threadInfoList = malloc ((N/2) *   sizeof(THREADINFO)); 

    pthread_t tid; 
    for(i = 0, k = 0; i < (N/2); i++){ 
     threadInputList[i].inputFile1 = inputFileList[k]; 
     threadInputList[i].inputFile2 = inputFileList[++k]; 
     threadInputList[i].targetBuf = i; 
     pthread_create(&(threadInfoList[i].tid), NULL, runBeginningThreads, &(threadInputList[i])); 

    } 
    for(i = 0; i< N/2 ; i++){ 
    pthread_join((threadInfoList[i]->tid), NULL); 
} 

    /* ... */ 

    /* While not strictly needed, you should make it a good 
     habit of freeing all you allocate */ 
    free(threadInfoList); 
    free(threadInputList); 

    return 0; /* You missed this */ 
} 
+0

あなたは正しいです。しかし、私が最後のスレッドを待つので、あなたが言ったようにではありません、最後のスレッドは出力を与えません。私がすべてのスレッドを待っていれば、この状況は変わっていません。私はすでに試してみました.N個のスレッドがあるとすれば、最初のN-1は正常に動作します。問題のあるものは最後のものです。 – Shnkc

+0

@Shnkc「最後の」スレッドと思われるものを待つことはできません。実行される順序は作成された順序と異なる場合があります。スレッドは互いに独立して実行されることに注意してください。 –

+0

OK Joachim Pileborg。私はポイントを得た。あなたが言ったようにすぐ上のコードを編集しています。しかし、同じ問題がまだ残っています。私はそれを正しい方法で修正できることを願っています。 – Shnkc