文件名未传入 pthread_create

filenames not passing into pthread_create

程序中有两个问题 首先,当我取消注释 main 函数中的 pthread_join() 时,将会出现段错误,否则程序将 运行... 其次,输出文件将丢失存储在上次读取文件的全局变量 words 中的每个单词的首字母。因此,例如,有两个文件:

一个有话"abc abc abc abc abc abc abc abc".

第二个有字"def def"

如果我在调用 a.out 时为第二个参数输入 5,输出文件中的输出将是 美国广播公司 美国广播公司 美国广播公司 美国广播公司 美国广播公司 公元前 公元前 公元前 定义 定义 这也是一个奇怪的事情,我不知道为什么。

/* main.c */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <ctype.h>
#include <pthread.h>
#include "hw3.h"
int index_;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

typedef struct files
{
    char *inputfile;
    FILE * outputfile;

} files;

void * readFile( void *arg ){

    files *info = (files *)arg;
    char fileName[80];
    strncat(fileName, (info->inputfile), 79);
    fileName[80] = '[=11=]';
    FILE *outputfd = info->outputfile;
    FILE* fd;
    fd = fopen(fileName, "r");
    if ( fd  == NULL) {
      fprintf(stderr, "ERROR:<open() failed>\n");
    }

    printf("TID %d: Opened \"%s\"\n", (unsigned int)pthread_self(), fileName);
    fflush(stdout);
    int rc;
    char ch[1] = {0};
    char word[80] = {0};
    ch[0] = fgetc(fd);
    pthread_mutex_lock(&mutex);
    while( ch[0] != EOF){
      if( isalnum(ch[0]) ){
      //  char str = ch[0];
      strncat(word, ch, 1);
      }
      else{//it's a word
        if( strlen( word ) >= 2 ){

          words[index_] = word;
          printf("TID %d: Stored \"%s\" in shared buffer at index [%d]\n",(unsigned int)pthread_self(), word, index_ );
          if( index_+ 1 == maxwords ){
            index_ = 0;
            printf("MAIN: Buffer is full; writing %d words to output file\n", maxwords);
            for( unsigned int i = 0; i<maxwords; i++ ){
              rc = fwrite(  words[i], 1, sizeof(words[i]), outputfd  );
              fwrite(  "\n", 1, sizeof("\n"), outputfd );
              if( rc == -1 ){
                fprintf(stderr, "ERRPR:<write() failed>\n");
                //return EXIT_FAILURE;
              }
            }
          }
          else{
            index_ ++;
          }
        }
        for(int i = 0; i< strlen(word); i++){
          word[i] = '[=11=]';
        }
      }
    ch[0] = fgetc(fd);
    }
    pthread_mutex_unlock(&mutex);
    printf("TID %d: Closed \"%s\"; and exiting\n", (unsigned int)pthread_self(), fileName );
    fclose(fd);
    pthread_exit( NULL );
}

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

  if(argc != 4){
  fprintf(stderr, "ERROR: Invalid arguments\nUSAGE: ./a.out <input-directory> <buffer-size> <output-file>\n");
    return EXIT_FAILURE;
  }
  //dynamically allocated words buffer with argument 2
  maxwords = atoi(argv[2]);
  words = (char**)calloc(maxwords, sizeof(char*) );

  if ( words == NULL)
  {
    fprintf( stderr, "ERROR:<word calloc() failed\n>" );
    return EXIT_FAILURE;
  }

  printf("MAIN: Dynamically allocated memory to store %d words\n", maxwords);
  fflush(stdout);

  //open/create output file of the third argument
  FILE* outputfd = fopen (argv[3], "w");
  if ( outputfd == NULL )
  {
    perror( "open() failed" );
    return EXIT_FAILURE;
  }
  DIR * dir = opendir( argv[1] );

  if(dir == NULL){
    perror("ERRPR:<opendir() failed>");
    return EXIT_FAILURE;
  }
  chdir(argv[1]);

  printf("MAIN: Opened \"%s\" directory\n", argv[1]);
  fflush(stdout);

  pthread_t tid[10];
  index_ = 0;
  int i = 0;//files index

  struct dirent * file;
  //files allfiles[20];
  char fileName[80];
  int rc;

  //-----------------------------------------------------------------------
  // while loop reads all files in the directory
  while ( ( file = readdir( dir ) ) != NULL )
  {
    struct stat buf;
    rc = lstat( file->d_name, &buf );  /* e.g., "xyz.txt" */
    /* ==> "assignments/xyz.txt" */

    if ( rc == -1 ){
      fprintf(stderr, "ERRPR:<lstat() failed>\n");
      return EXIT_FAILURE;
    }

    if ( S_ISREG( buf.st_mode ) )
    {
    //      printf( " -- regular file\n" );
   //      fflush(stdout);
      strncpy(fileName, file->d_name, 79);

      files info;
      info.inputfile = fileName;
      info.outputfile = outputfd;
      //printf("%d",i);
      printf("MAIN: Created child thread for \"%s\"\n",fileName);
      rc = pthread_create( &tid[i], NULL, readFile,(void *)&info );
      sleep(1);
      i++
    }
    else if ( S_ISDIR( buf.st_mode ) )
    {
    //      printf( " -- directory\n" );
    //      fflush(stdout);
    }
    else
    {
   //      printf( " -- other file\n" );
   //      fflush(stdout);
    }
  }

  closedir(dir);
  printf("MAIN: Closed \"%s\" directory\n", argv[1]);
  fflush(stdout);
  printf("MAIN: Created \"%s\" output file\n",argv[3]);
  fflush(stdout);
  //-----------------------------------------------------------------------

  for( int j = 0; j<i; j++){

      printf( "MAIN: Joined child thread: %u\n", (unsigned int)tid[j] );
      pthread_join(tid[i], NULL);
  }


  for( unsigned int i = 0; i<index_; i++ ){
    int rc = fwrite( words[i], 1, sizeof(words[i]), outputfd );
    if( rc == -1 ){
      fprintf(stderr, "ERRPR:<write() failed>\n");
      return EXIT_FAILURE;
    }
  }
  printf( "MAIN: All threads are done; writing %d words to output file\n", index_);
  fflush(stdout);

  free( words );
  fclose( outputfd );
  return EXIT_SUCCESS;
}

这是整个程序,还有一个头文件就是两个全局变量

char ** words = NULL;

/* global/shared integer specifying the size */
/*  of the words array (from argv[2])        */
int maxwords;

感谢大家的帮助!

每个线程需要单独的 info 个对象。现在,所有线程都获得相同的 info 对象,您可以在创建线程之间更改该对象,因此,对于大多数线程,当它们有机会查看文件名时,它们是应该处理,它已更改。

分段错误是由您未向我们展示的代码引起的,因此除了建议您应用 valgrind.

外,我无法帮助您解决这个问题

这里还有两个错误:

char fileName[80];
strncat(fileName, (info->inputfile), 79);

您只能连接到一个字符串,而不是一个可能包含也可能不包含有效字符串的单元化字符数组。

char ch[1] = {0};
char word[80] = {0};
ch[0] = fgetc(fd);
pthread_mutex_lock(&mutex);
while( ch[0] != EOF){

fgets 函数 returns 一个整数,它将 EOF 放在文件末尾,否则 returns 字符值。您将其转换为 char,然后将 charEOF 进行比较。但这没有任何意义,因为 EOF 是表示文件结尾的 integer 值。一旦转换为字符,它就是一个可以从文件中读取的有效字符,因为文件可以包含任何字符并且 "end of file" 不是字符。