Как pthreads вызывает ошибку сегментации в c (несмотря на то, что память не выделяется)? - PullRequest
0 голосов
/ 07 ноября 2018

Итак, я пытаюсь рекурсивно пройти по некоторому заданному каталогу и скопировать все содержимое каждого файла в каждом подкаталоге в выходной файл. Мне необходимо создать новый поток, чтобы скопировать файл, а также для перебора любых подкаталогов. Что я делаю, так это перебираю каталог, данный из терминала. При каждом вызове iterate_dir создается массив pthreads и счетчик для него, поэтому я могу закрыть каталог после объединения всех созданных потоков. Поэтому, если подкаталог был найден, я создаю pthread для вызова iterate_dir и передаю ему новый путь, увеличиваю массив pthread на единицу и сохраняю созданный pthread в нем. Если файл был найден, я создаю pthread для вызова copy_file, который открывает файл, читает его содержимое, сохраняя каждый символ в общую строку (которая является мьютексом и имеет динамический размер). Тем не менее, я продолжаю получать некоторые необъяснимые ошибки сегментации. Я ввожу каталог с 2 файлами и 2 подкаталогами, при этом 1 подкаталог пуст, а другой содержит 1 файл. Я попытался удалить copy_file и с ним pthread, который вызвал его, но я все еще получил segfault. Я попытался удалить массив pthreads, который я создал, но он все еще работал с ошибками. Я попытался пройти через это с помощью GDB, чтобы не получить окончательного ответа. Я предоставлю оба случая, один без copy_file и массива pthread, один с ними. Они оба сегфо. Мой вопрос, как работает pthread segfault, несмотря на то, что он даже ничего не выделяет (как в случае с кодом без copy_file и массивом pthread)? Я действительно озадачен, и мне было интересно, есть ли у кого-нибудь какие-либо идеи или советы по любому другому коду. Спасибо.

Без массива pthread и copy_file (ПРОСТО ЧИТАТЬ)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include <pthread.h>
#include <fcntl.h>

void* iterate_dir(void* args);


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

    char current_path[strlen(argv[1])+1];
    strcpy(current_path,argv[1]);


    pthread_t start;
    pthread_create(&start,NULL,&iterate_dir,current_path);
    pthread_join(start,NULL);

}



void* iterate_dir(void *args){


    DIR *dd = opendir((char*)args);
    struct dirent *curr;


    while((curr = readdir(dd))!=NULL){

        if(curr->d_type==DT_DIR && (strcmp(curr->d_name,".")==0 || strcmp(curr->d_name,"..")==0)){

            continue;

        }   

        if(curr->d_type==DT_DIR){


            char new_path[strlen(curr->d_name)+strlen((char*)args)+2];
            sprintf(new_path,"%s/%s",(char*)args,curr->d_name);
            pthread_t new_thread;
            pthread_create(&new_thread,NULL,&iterate_dir,new_path);


        }else{



        }


    }


    return NULL;

}

С copy_file и массивом pthread (HARDER TO READ)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include <pthread.h>
#include <fcntl.h>

void* iterate_dir(void* args);
void* copy_file(void* args);

pthread_mutex_t mut_for_final_string;
pthread_mutex_t mut_for_current_string_position;
char* final_string;
int current_string_position;


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

    char current_path[strlen(argv[1])+1];
    strcpy(current_path,argv[1]);
    char new_file_path[strlen(argv[2])+15+1];
    sprintf(new_file_path,"%s/%s",argv[2],"AllFiles-sorted");
    int output = open(new_file_path, O_WRONLY|O_CREAT, 0666);

    final_string = (char*)malloc(sizeof(char));
    current_string_position = 0;

    pthread_mutex_init(&mut_for_final_string,NULL);
    pthread_mutex_init(&mut_for_current_string_position,NULL);

    pthread_t start;
    pthread_create(&start,NULL,&iterate_dir,current_path);
    pthread_join(start,NULL);

    write(output,final_string,current_string_position);

    pthread_mutex_destroy(&mut_for_final_string);
    pthread_mutex_destroy(&mut_for_current_string_position);

}


void* copy_file(void *args){

    int input = open((char*)args,O_RDONLY);
    char c;

    while(read(input,&c,1)>0){

        pthread_mutex_lock(&mut_for_final_string);
        pthread_mutex_lock(&mut_for_current_string_position);
        final_string[current_string_position] = c;
        char* tmp = NULL;
        tmp = realloc(final_string,(current_string_position)+2);
        while(tmp==NULL){}
        final_string = tmp;
        (current_string_position)++;
        pthread_mutex_unlock(&mut_for_current_string_position);
        pthread_mutex_unlock(&mut_for_final_string);

    }

    close(input);

    return NULL;

}


void* iterate_dir(void *args){


    DIR *dd = opendir((char*)args);
    struct dirent *curr;
    pthread_t* tids = (pthread_t*)malloc(sizeof(pthread_t));
    int tids_counter = 0;



    while((curr = readdir(dd))!=NULL){

        if(curr->d_type==DT_DIR && (strcmp(curr->d_name,".")==0 || strcmp(curr->d_name,"..")==0)){

            continue;

        }   

        if(curr->d_type==DT_DIR){


            char new_path[strlen(curr->d_name)+strlen((char*)args)+2];
            sprintf(new_path,"%s/%s",(char*)args,curr->d_name);
            pthread_t new_thread;
            pthread_create(&new_thread,NULL,&iterate_dir,new_path);
            tids[tids_counter] = new_thread;
            tids_counter++;

            pthread_t* tmp_ptr = NULL;
            tmp_ptr = realloc(tids, (sizeof(pthread_t)*(tids_counter+1)));
            while(tmp_ptr==NULL){}
            tids = tmp_ptr;


        }else{

            char old_path[strlen(curr->d_name)+strlen((char*)args)+2];
            sprintf(old_path,"%s/%s",(char*)args,curr->d_name);
            pthread_t new_thread;
            pthread_create(&new_thread,NULL,&copy_file,old_path);
            tids[tids_counter] = new_thread;
            tids_counter++;

            pthread_t* tmp_ptr = NULL;
            tmp_ptr = realloc(tids, (sizeof(pthread_t)*(tids_counter+1)));
            while(tmp_ptr==NULL){}
            tids = tmp_ptr;


        }


    }

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

        pthread_join(tids[i],NULL);

    }

    closedir(dd);

    return NULL;

}

1 Ответ

0 голосов
/ 07 ноября 2018
char new_path[strlen(curr->d_name)+strlen((char*)args)+2];

Этот адрес памяти недействителен, как только вы покидаете область, в которой он был объявлен, но вы передаете этот адрес новому pthread.

...