1

EDITS ---------------- Я пробовал с gcc-4.8.1 и по-прежнему ту же ошибку .------- ------ Я пытаюсь реализовать простой пример умножения матрицы, используя pthreads через общую библиотеку. Но я получаю эту ошибку, когда я пытаюсь создать общую библиотеку:Ошибка сегментации/glibc при создании общей библиотеки

g++ -shared -o libMatmul.so matmul.o 
collect2: ld terminated with signal 11 [Segmentation fault], core dumped 

Вот код, я использую: matmul.h:

#ifndef matmul_h__ 
#define matmul_h__ 
#define SIZE 10 

typedef struct { 

int dim; 
int slice; 
} matThread; 

int num_thrd; 
int A[SIZE][SIZE], B[SIZE][SIZE], C[SIZE][SIZE]; 
int m[SIZE][SIZE]; 
extern void init_matrix(int m[SIZE][SIZE]); 
extern void print_matrix(int m[SIZE][SIZE]); 
extern void* multiply(void* matThread); 

#endif 

matmul.c:

extern "C" 
{ 
    #include <pthread.h> 
    #include <unistd.h> 
} 
#include <iostream> 
#include "matmul.h" 

using namespace std ; 
matThread* s=NULL; 
// initialize a matrix 
void init_matrix(int m[SIZE][SIZE]) 
{ 
    int i, j, val = 0; 
    for (i = 0; i < SIZE; i++) 
    for (j = 0; j < SIZE; j++) 
    m[i][j] = val++; 
} 

void print_matrix(int m[SIZE][SIZE]) 
{ 
    int i, j; 
    for (i = 0; i < SIZE; i++) { 
    cout<<"\n\t|" ; 
    for (j = 0; j < SIZE; j++) 
     cout<<m[i][j] ; 
     cout<<"|"; 
    } 
} 
// thread function: taking "slice" as its argument 
void* multiply(void* param) 
{ 
    matThread* s = (matThread*)param; // retrive the slice info 
    int slice1=s->slice; 
    int D= s->dim=10; 
    int from = (slice1 * D)/num_thrd; // note that this 'slicing' works fine 
    int to = ((slice1+1) * D)/num_thrd; // even if SIZE is not divisible by num_thrd 
    int i,j,k; 
    cout<<"computing slice " << slice1<<" from row "<< from<< " to " <<to-1<<endl; 
    for (i = from; i < to; i++) 
    { 
    for (j = 0; j < D; j++) 
    { 
     C[i][j] = 0; 
     for (k = 0; k < D; k++) 
     C[i][j] += A[i][k]*B[k][j]; 
    } 
    } 
    cout<<" finished slice "<<slice1<<endl; 
    return NULL; 
} 

main.c:

extern "C" 
{ 
#include <pthread.h> 
#include <unistd.h> 
} 
#include <iostream> 
#include "matmul.h" 
using namespace std; 

// Size by SIZE matrices 
// number of threads 
matThread* parm=NULL; 

int main(int argc, char* argv[]) 
{ 
    pthread_t* thread; // pointer to a group of threads 
    int i; 
    if (argc!=2) 
    { 
    cout<<"Usage:"<< argv[0]<<" number_of_threads"<<endl; 
    exit(-1); 
    } 
    num_thrd = atoi(argv[1]); 
    init_matrix(A); 
    init_matrix(B); 
    thread = (pthread_t*) malloc(num_thrd*sizeof(pthread_t)); 
    matThread *parm = new matThread(); 
    for (i = 0; i < num_thrd; i++) 
    { 
parm->slice=i; 
    // creates each thread working on its own slice of i 
    if (pthread_create (&thread[i], NULL, multiply, (void*)parm) != 0) 
    { 
     cerr<<"Can't create thread"<<endl; 
     free(thread); 
     exit(-1); 
    } 
    } 
for (i = 1; i < num_thrd; i++) 
    pthread_join (thread[i], NULL); 
    cout<<"\n\n"; 
    print_matrix(A); 
    cout<<"\n\n\t *"<<endl; 
    print_matrix(B); 
    cout<<"\n\n\t="<<endl; 
    print_matrix(C); 
    cout<<"\n\n"; 
    free(thread); 

    return 0; 

} 

Команды, которые я использую: g ++ -c -Wall -fPIC matmul.cpp -o matmul.o и g ++ -shared -o libMatmul.so matmul.o Код может выглядеть немного, потому что я пропускаю SIZE (dim) в структуре, когда она уже находится в #define, но именно так я хочу, чтобы она была реализована. Это тестовая программа для большего проекта, который я делаю. Любая помощь очень ценится! Заранее спасибо.

+1

какая версия GCC вы используете? –

+0

Я попытался с gcc 4.1, и это позволило мне создать общую библиотеку, но не смог связать ее с main. Когда я попытался с gcc-4.6.3, вышесказанное является ошибкой –

+0

. Я думал, что при использовании pthreads существует некоторый флаг компилятора/компоновщика. Что-то вроде -lpthread. – anonymous

ответ

1

Во-первых, вы смешиваете много C и C идиомы ++ (заходящих free и new, например), и вы не используете ++ функции библиотеки/STL C (как std::vector или std::list вместо массива C), поэтому, пока ваш код «технически» действителен (минус некоторые ошибки), не рекомендуется смешивать C и C++, как это, существует множество небольших отличий между C и C++ (например, синтаксис, компиляция и различия ссылок), которые могут добавить путаницу к коду, если это явно не ясно для намерений.

Это, как говорится, я сделал некоторые изменения в свой код, чтобы сделать его C++98 совместимость (и исправить ошибки):

matmul.h старт:

#ifndef matmul_h__ 
#define matmul_h__ 
#define SIZE 10 
#include <pthread.h> 

typedef struct matThread { 
    int slice; 
    int dim; 
    pthread_t handle; 

    matThread() : slice(0), dim(0), handle(0) {} 
    matThread(int s) : slice(s), dim(0), handle(0) {} 
    matThread(int s, int d) : slice(s), dim(d), handle(0) {} 
} matThread; 

// explicitly define as extern (for clarity) 
extern int num_thrd; 
extern int A[SIZE][SIZE]; 
extern int B[SIZE][SIZE]; 
extern int C[SIZE][SIZE]; 
extern void init_matrix(int m[][SIZE]); 
extern void print_matrix(int m[][SIZE]); 
extern void* multiply(void* matThread); 

#endif 

начала matmul.cpp:

#include <iostream> // <stdio.h> 
#include "matmul.h" 

int num_thrd = 1; 
int A[SIZE][SIZE]; 
int B[SIZE][SIZE]; 
int C[SIZE][SIZE]; 

// initialize a matrix 
void init_matrix(int m[][SIZE]) 
{ 
    int i, j, val; 
    for (i = 0, val = -1; i < SIZE; i++) { 
     for (j = 0; j < SIZE; j++) { 
      m[i][j] = ++val; 
     } 
    } 
} 

void print_matrix(int m[][SIZE]) 
{ 
    int i, j; 
    for (i = 0; i < SIZE; i++) { 
     std::cout << "\n\t|"; // printf 
     for (j = 0; j < SIZE; j++) { 
      std::cout << m[i][j]; 
     } 
     std::cout << "|"; // printf 
    } 
} 

// thread function: taking "slice" as its argument 
void* multiply(void* param) 
{ 
    matThread* s = (matThread*)param; // retrive the slice info 
    int slice1 = s->slice; 
    int D = s->dim = 10; 
    int from = (slice1 * D)/num_thrd; // note that this 'slicing' works fine 
    int to = ((slice1+1) * D)/num_thrd; // even if SIZE is not divisible by num_thrd 
    int i, j, k; 
    std::cout << "computing slice " << slice1 << " from row " << from << " to " << (to-1) << std::endl; // printf 
    for (i = from; i < to; i++) { 
     for (j = 0; j < D; j++) { 
      C[i][j] = 0; 
      for (k = 0; k < D; k++) { 
       C[i][j] += A[i][k]*B[k][j]; 
      } 
     } 
    } 
    std::cout << " finished slice " << slice1 << std::endl; // printf 
    return NULL; 
} 

начало main.cpp

#include <iostream> 
#include <cstdlib> // atoi .. if C++11, you could use std::stoi in <string> 
#include "matmul.h" 

int main(int argc, char** argv) 
{ 
    if (argc != 2) { 
     std::cout << "Usage: " << argv[0] << " number_of_threads" << std::endl; 
     return -1; 
    } else { 
     num_thrd = std::atoi(argv[1]); 
    } 
    matThread mt[num_thrd]; 
    int i = 0; 
    init_matrix(A); 
    init_matrix(B); 
    for (i = 0; i < num_thrd; i++) { 
     mt[i].slice = i; 
     // creates each thread working on its own slice of i 
     if (pthread_create(&mt[i].handle, NULL, &multiply, static_cast<void*>(&mt[i])) != 0) { 
      printf("Can't create thread\n"); 
      return -1; 
     } 
    } 
    for (i = 0; i < num_thrd; i++) { 
     pthread_join(mt[i].handle, NULL); 
    } 
    std::cout << "\n\n"; 
    print_matrix(A); 
    std::cout << "\n\n\t *\n"; 
    print_matrix(B); 
    std::cout << "\n\n\t=\n"; 
    print_matrix(C); 
    std::cout << "\n\n"; 
    return 0; 
} 

Чтобы скомпилировать и использовать его вам нужно выполнить следующие команды:

g++ -c -Wall -fPIC matmul.cpp -o matmul.o 
g++ -shared -Wl,-soname,libMatmul.so -o libMatmul.so.1 matmul.o 
ln /full/path/to/libMatmul.so.1 /usr/lib/libMatmul.so 
g++ main.cpp -o matmul -Wall -L. -lMatmul -pthread 

Обратите внимание, что для вашей системы, чтобы быть в состоянии найти и ссылку на общей библиотеке вы только что создали, вы вам нужно убедиться, что оно находится в папке lib вашего дистрибутива (например, /usr/lib/).Вы можете скопировать/переместить его, создать ссылку на него (или ссылку sym через ln -s, если вы не можете делать жесткие ссылки), и если вы не хотите копировать/перемещать/связывать ее, вы также можете LD_LIBRARY_PATH правильно настроен для включения каталога сборки.

Как я уже говорил; ваш код НЕ является неотъемлемо C++, кроме нескольких операторов печати (std::cout и т. д.), и сменив код C++ (std::cout на printf и некоторые другие второстепенные вещи, например), вы можете скомпилировать это как стандартный код C99. Я не уверен на 100%, как будет разработана остальная часть вашей общей библиотеки, поэтому я не изменил структуру кода lib (т. Е. Функции, которые у вас есть), но если вы хотите, чтобы этот код был «больше C++» (т.е. с классами/пространствами имен, STL и т. д.), вам в основном нужно будет перепроектировать ваш код, но, учитывая контекст вашего кода, я не думаю, что это абсолютно необходимо, если у вас нет конкретной потребности в нем.

Я надеюсь, что это может помочь.

+0

Спасибо, что помог мне здесь. Но я все равно получаю ту же ошибку !. Он все еще говорит 'collect2: error: ld, завершенный сигналом 11 [Ошибка сегментации], сбрасывается ядром'. Он скомпилирован для вас? Я использую gcc-4.8.1 –

+0

OK wait, он работает с gcc 4.1.2. Я не понимаю, почему! В любом случае Большое спасибо за помощь. Да, если его не слишком много, чтобы спросить, можете ли вы также мириться с C++ с 2-мя потоками? Я просто хочу быть уверенным в том, что делаю. Я думаю, что есть условие гонки при вызове 'pthread_create', потому что всякий раз, когда я вызываю 2 потока, активен только последний поток. Я думаю, что 'mt.slice = i' обновляется до 1 до использования значения 0. –

+0

Я знаю, что есть некоторые обновления для 4.8.1, которые «могут» сделать эту компиляцию по-разному (как разделяемую библиотеку); Я делаю свое собственное исследование по этому вопросу, поскольку я использую разные версии gcc, поэтому я опубликую любую вещь, которую я нахожу, почему она не может компилироваться в более новой версии. Я также отредактирую свой пост в дополнение к дополнениям C++. – txtechhelp

0

Если

for (i = 1; i < num_thrd; i++) 

не быть

for (i = 0; i < num_thrd; i++) 

Вы создали num_thrd темы, но не присоединиться ко всем из них, поэтому, состояние гонки создается как вы пытаетесь прочитать данные до завершения потока.

+0

Объясните, почему это работает. –

+1

Созданы потоки num_thrd, но не присоединились ко всем из них, поэтому условие гонки создается, когда вы пытаетесь прочитать данные до завершения потока. – robby987

+0

Пожалуйста, отредактируйте его в ответ. –

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