2015-02-11 3 views
1

Мой код (см. Ниже) вызывает странное поведение. Выход:pthread_join, похоже, меняет мой индекс цикла

Testing whether there are problems with concurrency ...rc is 0. i is 0 
.rc is 0. i is 0 
.rc is 3. i is 1 
.rc is 0. i is 0 
.rc is 3. i is 1 
.rc is 3. i is 2 
.rc is 0. i is 0 
.rc is 3. i is 1 
.rc is 3. i is 2 
.rc is 3. i is 3 
.rc is 0. i is 0 
.rc is 3. i is 1 
.rc is 3. i is 2 
.rc is 3. i is 3 
.rc is 3. i is 4 
.rc is 0. i is 0 
Segmentation fault (core dumped) 

Я пытался отладить ее, но только узнал, что я сброшен в 0, сразу после pthread_join. Это приводит меня к выводу, что модификация должна произойти где-то там. Но я ничего не могу найти. Я чувствую себя глупо, потому что это не очень сложный код. Что я не заметил?

Операционная система Ubuntu 14.04. N_THREADS в настоящее время установлен на 10, N_RUNS 10000.

Главная нить:

pthread_t threads[N_THREADS]; 
pthread_attr_t attr; 
int i; 
int rc; 
int status; 

printf("Testing whether there are problems with concurrency ..."); 

pthread_attr_init(&attr); 
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 

for (i = 0; i < N_THREADS; i++){ 
    if (i) { 
    rc = pthread_create(&(threads[i]), &attr, addRemove, 0); 
    } else { 
    rc = pthread_create(&(threads[i]), &attr, readStuff, 0); 
    } 
    if (rc) return rc; 
} 

for(i = 0; i < N_THREADS; i++) { 
    rc = pthread_join(threads[i], (void*) &status); 
// if(rc == 3) 
     printf("rc is %d. i is %d\n", rc, i); 
// if (rc) return rc; 
    if (status) return status; 
    printf("."); 
} 

pthread_attr_destroy(&attr); 

return 0; 

Рабочие потоки:

void* readStuff(void* a) 
{ 
    int i; 
    for (i = 0; i< N_RUNS; i++){ 
    ; 
    } 
    pthread_exit((void*)0); 
} 

void* addRemove(void* a) 
{ 
    int i; 
    for (i = 0; i< N_RUNS; i++){ 
    ; 
    } 
    pthread_exit((void*)0); 
} 

Там нет других нитей, кроме основного потока, и те, созданные в код выше.

Compileable example

+1

у вас есть две петли для соединения в части соединения. Это опечатка? – KiaMorot

+0

есть. Просто исправил это. – Martze

+0

Как получить полный, компилируемый пример? http://sscce.org/ – davmac

ответ

2

Я думаю, ваша проблема с pthread_join. От человека странице:

 
     int pthread_join(pthread_t thread, void **retval); 
     ... 

     If retval is not NULL, then pthread_join() copies the exit status of the tar‐ 
     get thread (i.e., the value that the target thread supplied to 
     pthread_exit(3)) into the location pointed to by *retval. If the target 
     thread was canceled, then PTHREAD_CANCELED is placed in *retval. 

Обратите внимание, что он принимает void **, что означает, что он переписывает вещь, на которую указывает retval с void * (размером 8 на 64 бит). Вы передаете int * (то есть &status), который является указателем на объект размером 4 на большинстве платформ.

Таким образом, pthread_join будет перезаписывать память. Вместо этого объявите status как void * в соответствии с прототипом функции.

Вы также тестируете status; Я не знаю, чего вы пытаетесь достичь здесь.

В целом, компиляция с -Wall покажет вам эти ошибки.

+0

-Wall -Wextra не сообщил мне об этом. Но это решило проблему! благодаря! Я прав, если я скажу, что этого не случилось бы на 32-битной системе? – Martze

+0

Да (я пропустил актерский состав). И да, 'sizeof (void *) == sizeof (int)' на 32 бит. – abligh

+1

Он не написал бы 8 байтов в 4-байтовую ячейку памяти на 32-битной, но ваш код все равно был бы неправильным, так как 'pthread_join' написал бы адрес' status' –

 Смежные вопросы

  • Нет связанных вопросов^_^