【问题标题】:C: Segmentation Fault on pthread_createC: pthread_create 上的分段错误
【发布时间】:2012-01-05 07:54:37
【问题描述】:

在 GCC 中运行我的程序时出现分段错误错误。这是一个相当长的程序,所以我只发布我认为相关的部分;如果需要更多信息,请告诉我。

void *RelaxThread(void *para) {
    printf("Entering RelaxThread...\n");
    struct Parameter *parameters;
    parameters = (struct Parameter *) para;
    /*Some code here*/
    pthread_exit(NULL);
}

int relax(double **matrix, int size, int threads, double precision) {
    keepRunning = 0;
    int rowAllocation = (size-2) / threads;     
    struct Parameter para[threads];
    pthread_t threadcount[threads];
    int current;
    int startRow = 1;
    long t;    
    for(t=0; t<threads; t++){       
        para[t].matrix = matrix;
        para[t].size = size;
        para[t].threads = threads;
        para[t].precision = precision;
        para[t].allocation = rowAllocation;
        para[t].threadId = t;
        para[t].startRow = startRow;
        startRow += rowAllocation;
        printf("DebugMsg1\n");
        current = pthread_create(&threadcount[t], NULL, RelaxThread, (void *) &para[t]);
        printf("DebugMsg2\n");
    }
    void *status;
    int rc;
    for(t=0; t<threads; t++) {
        rc = pthread_join(threadcount[t], &status);
        if (rc) {
            exit(-1);
        }
    }
    if (keepRunning) {
        printf("Iterating...\n");
        relax(matrix, size, threads, precision); 
    }
}

int main(int argc, char *argv[])
{
    int const size = 8;
    int const threads = 2;
    double const precision = 1e-6;
    double **matrix = (double **) malloc(size * sizeof(double));
    populateMatrix(matrix, size);
    relax(matrix, size, threads, precision);
    free(matrix);
    pthread_exit(NULL);
    return 0;
}

当 size 设置为 8 或以下时,代码运行良好。然而,任何比这更大的东西(它现在只支持偶数)在第二次迭代relax() 时会产生分段错误。因此,调试消息运行为:

Debug1
Debug2
Debug1
Debug2
Entering RelaxThread...
Entering RelaxThread...
Iterating...
Debug1
Debug2
Debug1
Segmentation Fault

它在大小为 8 或更少的情况下运行但在此数字以上崩溃的事实完全让我感到困惑,我花了很长时间试图弄清楚为什么会发生这种情况。我完全承认我的代码既不是最整洁也不是最有效的,但非常感谢一些关于为什么会失败的建议。

编辑 1:按要求附加 GDB 积压工作。

Debug1
[New Thread 0x40040940 (LWP 23270)]
Debug2
Debug1
Entering RelaxThread...
Entering RelaxThread 0
[New Thread 0x40081940 (LWP 23271)]
Debug2
Entering RelaxThread...
Entering RelaxThread 1
[Thread 0x40040940 (LWP 23270) exited]
Main: completed join with thread 0 having a status of 0
Main: completed join with thread 1 having a status of 0
Iterating...
Debug1
[Thread 0x40081940 (LWP 23271) exited]
[New Thread 0x40081940 (LWP 23272)]
Debug2
Debug1

Edit2:在更改后更新了回溯日志。

Edit3:下面是完整的 RelaxThread

    void *RelaxThread(void *para) {
        struct Parameter *parameters;
        parameters = (struct Parameter *) para;
        double **matrix = parameters->matrix;
        int size = parameters->size;
        double precision = parameters->precision;
        int threads = parameters->threads;
        int threadId = parameters->threadId;
        int startRow = parameters->startRow;
        int allocation = parameters->allocation;
        int finishRow = (startRow + allocation);
        int i;
        int j;
        double oldValue;
        double newValue;
        double difference;
        for(i=startRow;i<finishRow;i++) {
            for (j=1;j<size-1;j++) {
                pthread_mutex_lock (&mutexmatrix); //Tested with and without the mutex, which is globally defined and initialised elsewhere
                oldValue = matrix[i][j];
                newValue = ((matrix[i+1][j] + matrix[i-1][j] + matrix[i][j+1] + matrix[i][j-1]) / 4);
                matrix[i][j] = newValue;
                pthread_mutex_unlock (&mutexmatrix);
                difference = oldValue - newValue;
                if(difference < 0) {
                    difference = -difference; 
                }
                //printf("Precision on thread%d: %f , aiming for %f\n",threadId, difference,precision);
                if (difference > precision) {
                    keepRunning = 1;
                }
            }
        }
}

【问题讨论】:

  • 哦,我多么喜欢线程,在库方法中深度分段,在回溯中没有一行代码......无论如何,这相当小,所以还不错,但如果你能削减降到working example in as few lines as possible,那就更好了。
  • 哦,说到回溯,你能贴出来吗? gdb myprogram, r 运行它(如果需要,添加参数),等待它出现段错误,然后输入 bt。然后将其添加到您的帖子中。
  • 首先,您不应该以这种方式初始化具有动态大小的数组:struct Parameter para[threads];,因为这不是 ANSI-C 特性,有些编译器允许这样做,有些则不允许。
  • @Kevin 附上回溯,谢谢。
  • @felipemaia:这是 C99 的标准 ANSI-C 功能。它得到了很好的支持。

标签: c pthreads segmentation-fault


【解决方案1】:

正确的初始化,假设一个平方矩阵是:

double **matrix = malloc(size * sizeof(double *));
for(int i=0; i<size; i++)
{
    matrix[i] = malloc(size * sizeof(double));
    for(int j=0; j<size; j++)
    {
        matrix[i][j] = 0; // removing the junk contents
    }
}

编辑: 我也意识到你从来没有真正初始化过void *status。既然没用,改成rc = pthread_join(threadcount[t], NULL);,那肯定又是个问题了。

编辑3: 我发现的另一个问题是int startRow = 1;,我看不到你是如何访问矩阵的,但它的索引应该从 0 开始。

编辑4: 另外,当你释放一个二维数组时,你需要这样做:

for(int i=0; i<size; i++)
{
    free(matrix[i]);    //Free each row pointer
}
free(matrix);

【讨论】:

  • 谢谢,我已经更正了。不幸的是,崩溃似乎仍然在同一个地方发生。
  • 你在/*这里的一些代码*/里面做什么?那里有实际代码吗?还是稍后再添加?
  • 那里目前有代码,它从 startRow 遍历矩阵以获取 rowAllocation 行数,并将每个单元格替换为其四个邻居的平均值。 IE。一个放松的实施。然后它检查旧值和新值之间的差异是否大于指定的精度,如果是,则将 keepRunning 标记为 1 以表示应该再次运行relax()。我没有包含该代码,因为我认为问题出在 pthread_create
  • 按照建议更正了 pthread_join,但崩溃仍在继续
  • 将这些变量声明为全局变量,看看它是否有效struct Parameter para[32];pthread_t threadcount[32];
猜你喜欢
  • 1970-01-01
  • 2011-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-30
  • 1970-01-01
  • 2021-01-26
  • 1970-01-01
相关资源
最近更新 更多