2016-04-11 2 views
0

Я выполнил следующий код на Ubuntu 14.04 и CentOS 7 с помощью gcc-компилятора, но странно, что он показывает разные выходные данные для одних и тех же входов. Есть две проблемы, которые я не могу решить.Странный многопоточный вывод для разных платформ

  1. Я всегда получаю 0 в сумме (в основной функции) для самого первого умножения (1 * 1).
  2. Полностью неожиданный выход для Ubuntu. Вот код и оба выхода.

Код

#include<stdio.h> 
#include<pthread.h> 
#include<stdlib.h> 
#define N 15 
struct matrix 
{ 
    int num1, num2; 
}; 
void* multiply(void *c); 
int main() 
{ 
    int i, j, rows, cols, a[N][N], b[N][N], sum, k, final, res[N][N],*ptr; 
    pthread_t t1, t2; 
    struct matrix m1; 
    ptr=&sum; 
    printf("Enter the number of rows: "); 
    scanf("%d", &rows); 
    printf("Enter the number of cols: "); 
    scanf("%d", &cols); 
    for(i = 0; i < rows; i++) 
    { 
     for(j = 0; j < cols; j++) 
     { 
      printf("Enter the value at: a[%d][%d] : ", i, j);   
      scanf("%d", &a[i][j]); 
     } 
    } 
    for(i = 0; i < rows; i++) 
    { 
     for(j = 0; j < cols; j++) 
     { 
      printf("Enter the value at: b[%d][%d] : ", i, j);   
      scanf("%d", &b[i][j]); 
     } 
    } 
    for(i = 0; i < rows; i++) 
    { 
     for(j = 0; j < cols; j++) 
     { 
      final = 0; 
      for(k = 0; k < rows; k++) 
      { 
       m1.num1 = a[i][k]; 
       m1.num2 = b[k][j]; 
       pthread_create(&t1, NULL, (void*)multiply,(void*)&m1); 
       pthread_join(t1, (void**)&ptr); 
       sum=*ptr; 
       printf("\t%d",sum); 
       final += sum; 
       res[i][j] = final; 
      } 
      printf("\n"); 
     } 
    } 
    printf("The result is :\n"); 
    for(i = 0; i < rows; i++) 
    { 
     for(j = 0; j < cols; j++) 
     { 
      printf("%d\t", res[i][j]); 
     } 
     printf("\n"); 
    } 
    return 0; 
} 
void* multiply(void *c) 
{ 
    struct matrix *m; 
    m = (struct matrix *)c; 
    int p = 0; 
    p = m->num1 * m->num2; 
    printf("\t%d * %d = %d",m->num1,m->num2,p); 
    pthread_exit((void*)&p); 
} 

Выход для исполнения на Ubuntu

Enter the number of rows: 2 
Enter the number of cols: 2 
Enter the value at: a[0][0] : 1 
Enter the value at: a[0][1] : 2 
Enter the value at: a[1][0] : 3 
Enter the value at: a[1][1] : 4 
Enter the value at: b[0][0] : 1 
Enter the value at: b[0][1] : 2 
Enter the value at: b[1][0] : 3 
Enter the value at: b[1][1] : 4 
    1 * 1 = 1 0 2 * 3 = 6 32648 
    1 * 2 = 2 32648 2 * 4 = 8 32648 
    3 * 1 = 3 32648 4 * 3 = 12 32648 
    3 * 2 = 6 32648 4 * 4 = 16 32648 
The result is : 
32648 65296 
65296 65296 

Выход для исполнения на CentOS

Enter the number of rows: 2 
Enter the number of cols: 2 
Enter the value at: a[0][0] : 1 
Enter the value at: a[0][1] : 2 
Enter the value at: a[1][0] : 3 
Enter the value at: a[1][1] : 4 
Enter the value at: b[0][0] : 1 
Enter the value at: b[0][1] : 2 
Enter the value at: b[1][0] : 3 
Enter the value at: b[1][1] : 4 
    1 * 1 = 1 0 2 * 3 = 6 6 
    1 * 2 = 2 2 2 * 4 = 8 8 
    3 * 1 = 3 2 4 * 3 = 12 4 
    3 * 2 = 6 3 4 * 4 = 16 16 
The result is : 
6 10 
15 22 

ответ

1

multiply функция возвращает указатель на локальную переменную p, а время жизни локальной переменной заканчивается, как только функция заканчивается.

Самое простое решение здесь не использовать возвращаемое значение, но, чтобы зарезервировать место для результата в struct matrix, который передается multiply(), потому что структура выделяется в main. Изменить определение struct multiply:

struct matrix 
{ 
    int num1, num2; 
    int product; 
}; 

Изменить multiply() поставить результат здесь:

void *multiply(void *c) 
{ 
    struct matrix *m = c; 

    m->product = m->num1 * m->num2; 
    printf("\t%d * %d = %d", m->num1, m->num2, m->product); 
    return NULL; 
} 

Изменение main() для получения результата оттуда:

pthread_create(&t1, NULL, multiply, &m1); 
pthread_join(t1, NULL); 
sum = m1.product; 

(Side Примечание: эту переменную sum имеет запутанное имя, так как оно не содержит суммы!)

+0

Но на странице руководства pthread_join указано, что оно устанавливает значение, возвращаемое pthread_exit(), на целое число, указанное ptr (ptr в моей программе). Имея это в виду, я не должен просто получать значение p в сумме, если я объявляю ptr = & sum в начале? Я пытался это сделать, но это не сработало. [здесь] (http://man7.org/linux/man-pages/man3/pthread_join.3.html) - ссылка на эту страницу руководства. –

+1

Статус выхода, возвращаемый вашим потоком, не является целым указателем на: это сам указатель (указатель на переменную 'p' в' multiply() '). Это значение указателя успешно возвращается в 'ptr' на' pthread_join() ', но оно недействительно для использования больше, потому что указательная переменная' p' больше не существует. (Значение «*», которое целевой поток, указанный в «pthread_exit()' * », указанном на странице руководства, является значением * указателя *). – caf

+0

Кроме того, 'ptr' перезаписывается' pthread_join() ', поэтому не имеет значения, что вы установили в начале. Он заканчивается, указывая на 'p', но' p' больше не существует. – caf

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