Глобальный статический логический указатель вызывает ошибку сегментации с использованием Pthread

StackOverflow https://stackoverflow.com/questions/2982757

Вопрос

Новичок в программировании Pthread и застрял на этой ошибке при работе над смешанным кодом C ++ и C.

Что я сделал, так это назвать код C в потоке, созданный кодом C ++. Есть статический логический указатель is_center Используется в потоке и должен освободиться, когда поток заканчивается.

Однако я заметил, что каждый раз, когда программа обрабатывается в функцию C, значение логического указателя будет изменено, и затем ошибка сегментации произошла из -за Free (). И проблема происходит только тогда, когда используется код C. Удалите код C, а часть C ++ работает хорошо.

Подробный код заключается в следующем:

static bool *is_center;

// omit other codes in between ...

void streamCluster( PStream* stream)
{
    // some code here ...
    while(1){
        // some code here ...
        is_center = (bool*)calloc(points.num,sizeof(bool));

        // start the parallel thread here.
        // the c code is invoked in this function.
        localSearch(&points,kmin, kmax,&kfinal); // parallel

        free(is_center);
    }

И функция, использующая параллель, заключается в следующем (мой код C используется в каждом потоке):

void localSearch( Points* points, long kmin, long kmax, long* kfinal ) {
    pthread_barrier_t barrier;
    pthread_t* threads = new pthread_t[nproc];
    pkmedian_arg_t* arg = new pkmedian_arg_t[nproc];

    pthread_barrier_init(&barrier,NULL,nproc);

    for( int i = 0; i < nproc; i++ ) {
            arg[i].points = points;
            arg[i].kmin = kmin;
            arg[i].kmax = kmax;
            arg[i].pid = i;
            arg[i].kfinal = kfinal;
            arg[i].barrier = &barrier;

            pthread_create(threads+i,NULL,localSearchSub,(void*)&arg[i]);
    }

    for ( int i = 0; i < nproc; i++) {
        pthread_join(threads[i],NULL);
    }

    delete[] threads;
    delete[] arg;
    pthread_barrier_destroy(&barrier);
}

Наконец, функция, вызывающая мой код C:

void* localSearchSub(void* arg_) {                                                                                                                                                        

    int eventSet = PAPI_NULL;                                                                                                                                                                                                                                                                                                                                     
    begin_papi_thread(&eventSet);                                                                                                                                                         

    pkmedian_arg_t* arg= (pkmedian_arg_t*)arg_;                                                                                                                                             
    pkmedian(arg->points,arg->kmin,arg->kmax,arg->kfinal,arg->pid,arg->barrier);                                                                                                            

    end_papi_thread(&eventSet);                                                                                                                                                                                                                                                                                                                                                 

    return NULL;                                                                                                                                                                            
}   

И от GDB, что у меня есть для is_center является:

Breakpoint 2, localSearchSub (arg_=0x600000000000bc40) at streamcluster.cpp:1711
1711      end_papi_thread(&eventSet);
(gdb) s

Hardware watchpoint 1: is_center

Old value = (bool *) 0x600000000000bba0
New value = (bool *) 0xa93f3
0x400000000000d8d1 in localSearchSub (arg_=0x600000000000bc40) at streamcluster.cpp:1711
1711      end_papi_thread(&eventSet);

Какие-либо предложения? Заранее спасибо!

Некоторая новая информация о коде: для кода C я использую пакет PAPI. Я пишу свою собственную обертку PAPI для инициализации и чтения системных счетчиков. Код заключается в следующем:

void begin_papi_thread(int* eventSet)                                                                                                                                                     
{                                                                                                                                                                                         
    int thread_id = pthread_self();                                                                                                                                                       
    // Events                                                                                                                                                                             
    if (PAPI_create_eventset(eventSet)) {                                                                                                                                                 
        PAPI_perror(return_value, error_string, PAPI_MAX_STR_LEN);                                                                                                                        
        printf("*** ERROR *** Failed to create event set for thread %d: %s\n.", thread_id, error_string);                                                                                 
    }                                                                                                                                                                                     
    if((return_value = PAPI_add_events(*eventSet, event_code, event_num)) != PAPI_OK)                                                                                                     
    {                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
        printf("*** ERROR *** Failed to add event for thread %d: %d.\n", thread_id, return_value);                                                                                                                                                                                                                                                                         
    }                                                                                                                                                                                     
    // Start counting                                                                                                                                                                     
    if ((return_value = PAPI_start(*eventSet)) != PAPI_OK) {                                                                                                                                                                                                                                                                                                              
        PAPI_perror(return_value, error_string, PAPI_MAX_STR_LEN);                                                                                                                                                                                                                                                                                                         
        printf("*** ERROR *** PAPI failed to start the event for thread %d: %s.\n", thread_id, error_string);
    }                                                                                                                                                                                                                                                                                                                                                                             
}  
void end_papi_thread(int* eventSet)                                                                                                                                                       
{                                                                                                                                                                                         
    int thread_id = pthread_self();                                                                                                                                                       
    int i;                                                                                                                                                                                

    long long * count_values = (long long*)malloc(sizeof(long long) * event_num);                                                                                                         
    if (PAPI_read(*eventSet, count_values) != PAPI_OK)                                                                                                                                    
        printf("*** ERROR *** Failed to load count values.\n");                                                                                                                           

    if (PAPI_stop(*eventSet, &dummy_values) != PAPI_OK) {
        PAPI_perror(return_value, error_string, PAPI_MAX_STR_LEN);
        printf("*** ERROR *** PAPI failed to stop the event for thread %d: %s.\n", thread_id, error_string);
        return;
    }
    if(PAPI_cleanup_eventset(*eventSet) != PAPI_OK)
        printf("*** ERROR *** Clean up failed for the thread %d.\n", thread_id);                                                                                                          
} 
Это было полезно?

Решение

Я не думаю, что вы опубликовали достаточно кода, чтобы по -настоящему понять вашу проблему, но выглядит подозрительно, что вы объявили is_center Глобальный. Я предполагаю, что вы используете его в более чем одном месте, возможно, несколькими потоками (localSearchSub Упоминает это, что является вашей функцией рабочей потока).

Если is_center читается или написано несколькими потоками, вы, вероятно, хотите защитить его с помощью Pthread Mutex. Анкет Вы говорите, что это «освобождено, когда поток заканчивается», но вы должны знать, что есть nprocs темы, и, похоже, они все работают над множеством is_center[points] Bools. Если points != nproc, это может быть плохо [1]. Каждый поток, вероятно, должен работать на собственном массиве, и localSearch Следует объединить результаты.

А xxx_papi_thread Функции не получают никаких хитов в Google, поэтому я могу только представить, что это ваша собственная ... вряд ли мы сможем вам помочь, если проблема там :)

1]: даже если points == nproc, не обязательно можно писать в разные элементы массива из нескольких потоков (это зависит от компилятора и процессора). Будьте в безопасности, используйте мутекс.

Кроме того, это помечено C++. Анкет Можете ли вы заменить calloc и динамические массивы (используя new) с vectors? Это может быть легче отладить, и это, безусловно, в конечном итоге легче поддерживать. Почему вы ненавидите и хотите наказать читателей вашего кода? ;)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top