Ошибка сегментации при соединении с потоком № 5 (pthread_join)

Пытаюсь решить небольшую проблему синхронизации. но когда я присоединяюсь к потокам, я получаю ошибку сегмента пятой итерации! Если я создаю только 4 потока, работает отлично.

Здесь я оставляю код с некоторыми основами того, что делать с потоком.

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

sem_t HackersEmploy_Counter;
int hackerOnBoat, employOnBoat, B, b, hackerResagado, employResagado;

sem_t Board;
int onBoatId[4];     
char onBoatType[4]; 

sem_t Bote;  

typedef struct{
    FILE* log;
    int ID;
}param;

void* HackerArrive(void* para){
    param* var = (param*) para;
    printf("Create Hacker %i\n", var->ID-1);
    pthread_exit(0);
}

void* EmployeeArrive(void* para){
    param* var = (param*) para;
    printf("Create Employee %i\n", var->ID-1);
    pthread_exit(0);
}

int main(int argc, char **argv) {
    sem_init(&HackersEmploy_Counter,0,1);
    sem_init(&Bote,0,4);
    sem_init(&Board,0,1);
    FILE* log;
    log = fopen("result_simulacion.txt", "w");
    int E, e=1, H, h=1, i, r;
    hackerOnBoat=0; employOnBoat=0; b=1; hackerResagado=0; employResagado=0;
    for (i=1; i<argc; i++){
        if (strcmp(argv[i],"-h")==0){
            i++;
            H = atoi(argv[i]);
        }
        if (strcmp(argv[i],"-e")==0){
            i++;
            E = atoi(argv[i]);
        }
        if (strcmp(argv[i],"-b")==0){
            i++;
            B = atoi(argv[i]);
        }
    }
    pthread_t* bank = (pthread_t*) malloc( (E+H) * sizeof (pthread_t*));
    param* var = (param*) malloc( (E+H) + sizeof (param*));
    for (i=0; i<H+E; i++){
        r = rand() % 2;
        if (r==0){
            if (h<=H){
                var[i].log = log;
                var[i].ID = h;
                pthread_create(&bank[i], NULL, HackerArrive, (void*) &var[i]);
                h++;
            }else{
                var[i].log = log;
                var[i].ID = e;
                pthread_create(&bank[i], NULL, EmployeeArrive, (void*) &var[i]);
                e++;
            }
        }else{
            if (e<=E){
                var[i].log = log;
                var[i].ID = e;
                pthread_create(&bank[i], NULL, EmployeeArrive, (void*) &var[i]);
                e++;
            }else{
                var[i].log = log;
                var[i].ID = h;
                pthread_create(&bank[i], NULL, HackerArrive, (void*) &var[i]);
                h++;
            }
        }
    }
    for (i=0; i<E+H; i++){
        pthread_join(bank[i], NULL);
        printf("join %i\n", i);
    }
    return 0;
}

запустить с: ./work -h 4 -e 0 -b 1

они работают с: ./work -h 5 -e 0 -b 1

если они увеличивают значение "-h" более чем на 4, получают ошибку сегментации

Почему это?


person Cesar J Rodriguez    schedule 25.10.2013    source источник
comment
Откатился на первоначальную ревизию. (потратив 10 минут на поиск очевидных ошибок, которые я не смог найти, потому что они были исправлены) Исправление ошибок в вопросе сделало бы вопросы и ответы бесполезными для будущих читателей.   -  person wildplasser    schedule 26.10.2013


Ответы (2)


Пожалуйста, будьте внимательнее при чтении кода. Этот:

param* var = malloc((E+H) + sizeof(*var));

должно быть так:

param* var = malloc((E+H) * sizeof(*var));
//                        ^

Ваш код работает (или, по крайней мере, не падает) для меня после этого изменения:

paul@local:~/src/c/scratch$ ./thread -h 2 -e 2 -b 2
Create Employee 0
Create Hacker 1
Create Employee 1
Create Hacker 0
join 0
join 1
join 2
join 3
paul@local:~/src/c/scratch$

Использование такого инструмента, как valgrind, помогло бы вам отследить это за считанные минуты.

Как упоминалось в моем другом комментарии, вы должны проверять возврат каждый раз, когда вы вызываете такие функции, как malloc(), fopen(), pthread_create(), pthread_join() и т. д., иначе вы абсолютно не знаете, игнорируете ли вы важные ошибки, которые пытаются сообщить ваши функции. ты о.

person Crowman    schedule 26.10.2013
comment
Хорошее место - +1. Я не заметил, что в исходном коде было две ошибки. Мне потребовалась целая вечность, чтобы заметить, что вы изменили, поэтому я позволил себе отредактировать ваш ответ, чтобы выделить проблему. - person simonc; 26.10.2013
comment
@simonc: Нет проблем, наверное, надо было подумать о том, чтобы выделить это самому, спасибо! - person Crowman; 26.10.2013

Распределение для вашего массива pthread_ts не совсем правильное. Вы хотите выделить память для массива из pthread_t экземпляров, но в настоящее время выделяете место только для указателей.

Не выделяя место для правильного типа, вы рискуете записать за пределы выделенной памяти, когда позже будете писать в этот массив. Это имеет неопределенные последствия; в этом случае вы, вероятно, перезапишете память, используемую другими частями вашей программы. Это вполне может вызвать segfault.

Вы должны изменить распределение следующим образом

pthread_t* bank = malloc((E+H) * sizeof(*bank));

Та же проблема относится к массиву param var, который должен быть выделен как

param* var = malloc((E+H) + sizeof(*var));

Обратите внимание, что для вас будет хорошей практикой free эти массивы позже в вашей программе.

for (i=0; i<E+H; i++){
    pthread_join(bank[i], NULL);
    printf("join %i\n", i);
}
free(bank);
free(var);
person simonc    schedule 25.10.2013
comment
Спасибо за ответ, я сделал то, что вы сказали, но все равно выдает segfault! что может быть? - person Cesar J Rodriguez; 26.10.2013
comment
Нет смысла задавать такие вопросы, пока вы не исправите свой код. Вы не проверяете возврат из одной одной из ваших функций, ни malloc(), ни fopen(), ни pthread_create(), ни pthread_join, ничего. Если вы не проверяете, возвращают ли эти функции сообщения об ошибках, то не удивляйтесь, если вы их обнаружите. Вы также не проверяете, есть ли у вас допустимые аргументы командной строки. Если вы получаете ошибки в своем коде, первое, что вы должны попробовать, это добавить в него правильную проверку ошибок. - person Crowman; 26.10.2013
comment
@CesarJRodriguez См. ответ Пола Гриффитса. Расчет размера памяти var был менее неправильным, но все же неверным в моем ответе. - person simonc; 26.10.2013