创建共享库时检测到分段错误/ glibc

时间:2014-02-07 11:07:34

标签: c++ multithreading segmentation-fault pthreads shared-libraries

编辑----------------我尝试使用gcc-4.8.1并仍然出现同样的错误.-----------我正在尝试通过共享库实现使用pthreads的简单矩阵乘法示例。但是当我尝试创建共享库时,我收到此错误:

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 代码可能看起来很少,因为我在#define中已经在结构中传递SIZE(昏暗),但这是我希望它实现的方式。它是我正在做的更大项目的测试程序。 任何帮助是极大的赞赏!提前致谢。

2 个答案:

答案 0 :(得分:1)

首先,你混合了许多C和C ++习语(例如调用freenew)并且你没有使用任何C ++库/ STL特性(比如{{1 }}或std::vector,而不是C数组),所以当你的代码是“技术上”有效(减去一些错误)这不是很好的做法,混合C和C ++这样的,有C和之间有许多细小的特质差异C ++(例如语法,编译和链接差异),如果没有明确表达意图,可能会给代码增加混淆。

话虽如此,我已对您的代码进行了一些更改,以使其std::list兼容(并修复错误):

开始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;
}

请注意,为了让您的系统能够查找和链接您刚刚创建的共享库,您需要确保它位于您的发行版的lib文件夹中(如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 )。你可以复制/移动它,创建一个链接(如果你不能做硬链接,可以通过/usr/lib/进行sym链接),如果你不想复制/移动/链接它,你可以还可以确保正确设置ln -s以包含构建目录。

正如我所说;您的代码本质上不是C ++,除了少数打印语句(LD_LIBRARY_PATH等),并且将C ++代码(std::cout更改为std::cout以及其他一些小事例),您可以编译这是标准的printf代码。我不是100%确定你的共享库的其余部分是如何设计的,所以我没有改变lib代码的结构(即你拥有的函数)但是如果你想要这个代码是'更多的C ++'(即对于类/命名空间,STL等),您基本上需要重新设计代码,但考虑到代码的上下文,我认为除非您有特殊需要,否则绝对没有必要。

我希望可以提供帮助。

答案 1 :(得分:0)

应该

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

不是

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

您创建了num_thrd个线程,但没有加入所有线程,因此,在线程完成之前尝试读取数据时会创建竞争条件。