Схожу с ума из-за простой ошибки сегмента, вызванной pthread_create () - PullRequest
0 голосов
/ 25 октября 2018

В этом коде я пытаюсь создать массив потоков.Я установил значение pthreads в 1. В цикле for печатается адрес, ID и «созданный», но функция никогда не выполняется, так как я не получаю печать.

Ошибка seg на самом деле происходит в pthread_join внизу, но это, безусловно, должно быть вызвано созданием, так как функция никогда не запускается, верно?Производители [0] - единственный поток, так как я просто тестирую 1. Функция create передает (ID-адрес, NULL, аргументы void * function () и void *), как и положено.Это должно быть что-то очевидное, но я пытался понять это так долго, что я пустой.

typedef struct ThreadStruct {
    int threadIndex;

} ThreadStruct;


void *producer(void* ts){
    printf("in producer\n");
    FILE* inputfp = threadstruct->inputFiles[0];

    hostname = (char*)malloc((MAXNAME+1)*sizeof(char));
    while(fscanf(inputfp, hostname) > 0){
        printf("%s",hostname);
    }

    return 0;
}

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

    int pthreads = atoi(argv[1]); //always 1
    ThreadStruct threadstruct;
    pthread_t producers[pthreads];

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

        printf("in pthread loop\n");
        printf("%p \n",&producers[i]);
        printf("%ld \n",producers[i]);
        pthread_create(&producers[i], NULL, producer, (void *) &threadstruct); 
    }
    pthread_join(producers[0], NULL);
}

Ответы [ 3 ]

0 голосов
/ 25 октября 2018

Ваш код работает на моей стороне и не вызывает ошибку сегмента.Вот распечатка информации:

$ ./pthread
in pthread loop
0xffffcb70
6444554784
in pthread loop
in producer
0xffffcb78
64
in pthread loop
in producer
0xffffcb80
1
in pthread loop
in producer
0xffffcb88
4299166064
in pthread loop
in producer
0xffffcb90
6443761969
in pthread loop
in producer
0xffffcb98
6445451520
in pthread loop
in producer
0xffffcba0
314761761601
in producer
exit main thread

Ваш код здесь:

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>

typedef struct ThreadStruct {
    int threadIndex;

} ThreadStruct;


void *producer(void* ts){
    printf("in producer\n");
    return 0;
}

int main(int argc, char *argv[]){
    int pthreads = 7;
    ThreadStruct threadstruct;
    pthread_t producers[pthreads];

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

        printf("in pthread loop\n");
        printf("%p \n",&producers[i]);
        printf("%ld \n",producers[i]);
        pthread_create(&producers[i], NULL, producer, (void *) &threadstruct); 
    }
    pthread_join(producers[0], NULL);

    printf("exit main thread\n");
}
0 голосов
/ 25 октября 2018

Сначала проверьте возвращаемое значение pthread_create(), чтобы проверить, было ли оно успешным или нет.Например,

int ret = pthread_create(&producers[i], NULL, producer, (void *) &threadstruct);
if(ret) {
   fprintf(stderr, "failed to create thread %s\n",strerror(ret));
   exit(EXIT_FAILURE);
}

И также рекомендуется использовать pthread_join() для всех потоков, а не только для первого потока, как если бы вы хотели дождаться завершения потока / с перед дальнейшей обработкой в ​​основном потоке, как упоминалось здесь .Также проверьте возвращаемое значение pthread_join().

Пример кода

#include<stdio.h>
#include<string.h>
#include<stdint.h>
#include<stdlib.h>
#include<pthread.h>
typedef struct ThreadStruct {
        int threadIndex;
} ThreadStruct;
void *producer(void* ts){
        printf("in producer\n");
        return 0;
}
int main(int argc, char *argv[]){
        int pthreads = 5;
        int ret;
        ThreadStruct threadstruct;
        pthread_t producers[pthreads];
        /* create threads */
        for(intptr_t itr = 0;itr < pthreads; itr++){
                printf("in pthread loop\n");
                //printf("%p \n",&producers[itr]);
                //printf("%ld \n",producers[itr]);
                ret = pthread_create(&producers[itr], NULL, producer, (void *) &threadstruct);
                if (ret) {
                        fprintf(stderr, "failed to create thread #%ld - %s\n",(long)itr, strerror(ret));
               exit(EXIT_FAILURE);
                }
        }
        /* join all threads */
        for(intptr_t itr = 0; itr < pthreads; itr++){
                printf("In main: joining thread #%ld\n", (long)itr);
                ret = pthread_join(producers[itr], NULL);
                if (ret) {
                        fprintf(stderr, "failed to join thread #%ld - %s\n",(long)itr, strerror(ret));
               exit(EXIT_FAILURE);
                }
        }
        //pthread_exit();
        return 0;
} 

он работает в моей системе, надеюсь, он работает и для вас.

0 голосов
/ 25 октября 2018

вы, кажется, не проверяете , создан ли поток на самом деле или нет , другими словами, вы, кажется, не проверяете тип возврата pthread_create и прямой вызов pthread_join, вероятно, ведущийв Неопределенное поведение , в случае сбоя pthread_create.

pthread_create(&producers[i], NULL, producer, (void *) &threadstruct);

из pthread_join

   The pthread_join() function shall fail if:

   EINVAL The implementation has detected that the value specified by thread does not refer to a joinable thread.

   ESRCH  No thread could be found corresponding to that specified by the given thread ID.

однако существуют случаи, когда pthread_join с ошибками сегмента дескриптора потока .

фрагмент извлечения из ссылки выше


"* Передача неверного дескриптора в pthread_join похожа на передачу неверного указателя на системный вызов.

Реализация может обнаружитьэто и сигнализирует об этом по ошибке, но это также может привести к сбою.

В Red Hat Linux есть 2 различных реализации потоков POSIX

  • linuxthreads, где дескриптор pthread_t представляет собой небольшое целое число (и количество потоков существенно ограничено)
  • NPTL (по умолчанию pthread_t является внутренним указателем, чтобы не было произвольных ограничений потоков)

Вы можете запросить старомодныйбиблиотека потоков с LD_ASSUME_KERNEL = 2.4.19 в среде.

Для NPTL, где pthread_t - указатель, pthread_join обнаруживает некоторые недействительные дескрипторы, где это можно сделать дешево. Но обнаружение всех возможных недействительных дескрипторов будет очень дорогостоящим (Реализация в основном должна была бы взять глобальную блокировку и перебрать все текущие запущенные потоки,позвоните ручку с каждым из них.С помощью, скажем, 100000 запущенных потоков вы можете увидеть, насколько это дорого).

Этот тестовый пример работает на SuSE, поскольку SuSE поставляется только с устаревшей немасштабируемой реализацией linuxthreads. * "


от pthead_create

RETURN VALUE
       On success, pthread_create() returns 0; on error, it returns an error number, and the contents of *thread are undefined.

возможно что-то вроде этого

if( pthread_create(&producers[i], NULL, producer, (void *) &threadstruct)  ) {
   perror("something wrong .. ");
   exit(1);
}
...