2013-07-31 5 views
0

У меня есть следующий код, который вызывает ошибку *** glibc detected *** free(): invalid pointer всякий раз, когда я запускаю код.*** glibc detected *** free(): invalid pointer

main.h:

#ifndef PTHREAD_CALC_H_ 
#define PTHREAD_CALC_H_ 

void* task(void*); 

#endif 

main.cxx:

#include <stdio.h> 
#include <stdlib.h> 
#include <sys/time.h> 
#include <pthread.h> 
#include "main.h" 

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

    pthread_t *threads = (pthread_t*)malloc(sizeof(pthread_t)*2); 
    double *temp; 

    double sum = 0.0; 
    for (int j = 0; j < 2; j++) { 
     pthread_create(&(threads[j]), NULL, task, NULL); 
    } 

    for (int j = 0; j < 2; j++) { 
     pthread_join(threads[j], (void**)(&temp)); 
     sum += *temp; 
    } 

    free(threads); 
    free(temp); 

    return 0; 
} 

void* task(void *data) { 
    double sum = 5; 
    pthread_exit((void*)&sum); 
    return NULL; 
} 

Я с трудом определяют, что является причиной ошибки. Любая помощь очень ценится. Если я могу предоставить что-нибудь еще, чтобы помочь выявить проблему, пожалуйста, дайте мне знать.

Спасибо

Редактировать

Ради завершенности, здесь результирующий код, который выполняется, как ожидалось:

main.cxx:

#include <stdio.h> 
#include <stdlib.h> 
#include <sys/time.h> 
#include <pthread.h> 
#include "main.h" 

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

    pthread_t *threads = (pthread_t*)malloc(sizeof(pthread_t)*2); 
    double *temp; 

    double sum = 0.0; 
    for (int j = 0; j < 2; j++) { 
     pthread_create(&(threads[j]), NULL, task, NULL); 
    } 

    for (int j = 0; j < 2; j++) { 
     pthread_join(threads[j], (void**)&temp); 
     sum += temp; 
     delete temp; 
    } 

    free(threads); 
    return 0; 
} 

void* task(void *data) { 
    double* sum = new double; 
    *sum = 5.0; 
    pthread_exit(static_cast<void*>(sum)); 
} 
+1

неродственной, но вы передаете назад ссылку просуммировать из задачи , но сумма находится в стеке. Эта переменная может не существовать, когда вы добавляете ее в переменную sum в main. – MWB

+0

@MWB не является точкой 'pthread_join()'? Он блокирует родительский поток до завершения задачи. Это заставляет меня думать, что 'sum' должно существовать, и его значение должно храниться в' temp' –

+1

На странице man (http://man7.org/linux/man-pages/man3/pthread_exit.3.html) Значение, указанное retval, не должно находиться в стеке вызывающего потока, так как содержимое этого стека не определено после завершения потока. – MWB

ответ

1

В настоящее время задача вашего потока возвращает некоторое значение в стеке потока. Когда нить заканчивается, нет никакой гарантии, что * temp указывает на что-то действительное.

Таким образом, после этого вызова

pthread_join(threads[j], (void**)(&temp)); 

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

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

free(temp); 

хочет вы можете сделать, это:

void* task(void *data) { 
    double* sum = new double; 
    *sum = 5; 
    pthread_exit(static_cast<void*>(sum)); 
} 

, а затем в основном после присоединения нити

delete temp; 
+0

С вашей помощью я нашел решение. Я буду обновлять исходное сообщение, чтобы содержать код, который вызывает ожидаемое поведение. –

+0

@AlexBrooks Рад помочь, но вы не должны сильно менять свой код в своем сообщении, поэтому мне сложно постоянно обновлять свой ответ, когда вы продолжаете обновлять свой вопрос. – hetepeperfan

+0

Конечно. Я просто не хотел, чтобы люди жаловались, что код слишком длинный. Мне следовало подождать, пока я выпустил сокращенный код. Я буду помнить об этом в следующий раз. –

0

В своем коде вы объявляете :

double *temp; 

Вы никогда не malloc по адресу, но позже вы его бесплатно. Это приведет к ошибке. Удалите свободный (temp), и он должен работать. На самом деле, хотя вы ввели новые ошибки при разыменовании * temp без хранения.

+0

Wow я чувствую себя немым ... Я не знаю, как я это пропустил. Спасибо. Теперь мне просто нужно выяснить, как получить значение суммы в 'temp' ... –

+0

Этого недостаточно, поскольку MWB указывается в комментариях выше. Это, как описано в настоящее время, приведет к неопределенному поведению, так как * temp укажет на переменную в стеке потоков. – hetepeperfan

+1

Право. Код OP несколько раз менялся между моими сообщениями. IIRC, исходное сообщение действительно делало malloc для temp, но освобождало его в task() и в конце программы. В любом случае выбранный ответ правильный для текущего кода. – Cos314

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