使用 pthread_create 时出现段错误

Seg Fault when using pthread_create

我在使用 pthread_create 时难以创建线程,我尝试将函数更改为 void* 等,但它一直抛出分段错误。

任何解决此问题的帮助将不胜感激,我已尝试研究此问题但无济于事我还没有找到解决方案

下面是我的代码:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <ctype.h>
#include <getopt.h>
#include <stdbool.h>

void readSudoku(int x[][9], FILE *in);
void printSudoku(int x[][9]);
int validateRows(int x[9][9]);
int validateCols(int x[9][9]);
int validateSubGrids(int x[9][9]);
void *vr(int x[9][9]);
void *vc(int x[9][9]);
void *vs(int x[9][9]);
bool validSudokuGrid(int x[][9]);

/* These are the only two global variables allowed in your program */
static int verbose = 0;
static int use_fork = 0;

// This is a simple function to parse the --fork argument.
// It also supports --verbose, -v
void parse_args(int argc, char *argv[])
{
    int c;
    while (1)
    {
        static struct option long_options[] =
            {
                {"verbose", no_argument, 0, 'v'},
                {"fork", no_argument, 0, 'f'},
                {0, 0, 0, 0}};
        int option_index = 0;
        c = getopt_long(argc, argv, "vf", long_options, &option_index);
        if (c == -1)
            break;

        switch (c)
        {
        case 'f':
            use_fork = 1;
            break;
        case 'v':
            verbose = 1;
            break;
        default:
            exit(1);
        }
    }
}

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

    // Commented this out because this will be used later
    // parse_args(argc, argv);

    // if (verbose && use_fork) {
    //     printf("We are forking child processes as workers.\n");
    // } else if (verbose) {
    //     printf("We are using worker threads.\n");
    // }

    // printf("Test");

    // Initializing sudoku grid to parse file grid
    int sudoku_grid[9][9];

    if (argc == 1)
    {
        printf("File successfully opened!\n");
    }

    readSudoku(sudoku_grid, stdin);
    printSudoku(sudoku_grid);
    // validateRows(sudoku_grid);
    // validateCols(sudoku_grid);
    if (validSudokuGrid(sudoku_grid))
    {
        printf("The input is a valid Sudoku. \n");
    }
    else
    {
        printf("The input is not a valid Sudoku. \n");
    }

    return 0;
}

void readSudoku(int x[][9], FILE *in)
{
    fseek(in, -1, SEEK_CUR); // Seek to start off the current position of the file ptr

    char entry;
    int i, j, totalVals = 0;

    while ((fread(&entry, 1, 1, in)) > 0 && totalVals < 81)
    { // Read 81 digits from stdin file
        if (entry != '\n')
        { // Ignore newline
            if (isdigit(entry))
            {
                ++totalVals;
                x[i][j] = entry - '0'; // Store integer representation
                ++j;
                if (j == 9)
                {
                    j = 0;
                    ++i;
                }
            }
        }
    }
}

void printSudoku(int x[][9])
{
    int i = 0, j = 0; // i = rows, j = cols
    for (i = 0; i < 9; i++)
    {
        for (j = 0; j < 9; j++)
        {
            // if we are on the third or fifth number of sub-grid
            // we make a space between nums
            if (2 == j || 5 == j)
            {
                printf("%d   ", x[i][j]);
            }
            // if we are on the last num of row we make a space
            else if (8 == j)
            {
                printf("%d\n", x[i][j]);
            }
            // anything else we make a space
            else
            {
                printf("%d ", x[i][j]);
            }
        }
        // if we are on row 3 or row 5 we make a space
        if (2 == i || 5 == i)
        {
            printf("\n");
        }
    }
}

// Used to validate rows per 3x3 grid
int validateRows(int x[9][9])
{
    for (int i = 0; i < 9; i += 3)
    {
        for (int j = 0; j < 9; j += 3)
        {
            int subgridValidate[9] = {0};

            for (int k = i; k < i + 3; k++)
            {
                for (int m = j; m < j + 3; m++)
                {
                    int currVal = x[k][m];
                    if (subgridValidate[currVal - 1] == 0)
                    {
                        subgridValidate[currVal - 1] = 1;
                    }
                    // else
                    // {
                    //     // printf("row: %d, col: %d", k+1, m+1);
                    //     // printf("Row: %d does not have required values \n", k + 1);
                    //     // printf("Column: %d does not have required values \n", m + 1);
                    //     return 0;
                    // }
                    else if((subgridValidate[currVal - 1] == 1) && (k >= 0 && k <=2)) {    // checks for dupes, segfaults if num > 9
                        if( m >= 0 && m <= 2 ){
                            printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
                            return 0;
                        }
                        else if ( m >= 3 && m <= 5 ){
                            printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
                            return 0;
                        }
                        else if ( m >= 6 && m <= 8 ){
                            printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
                            return 0;
                        }
                    }
                    else if((subgridValidate[currVal - 1] == 1) && (k >= 3 && k <=5) ) {    // checks for dupes, segfaults if num > 9
                        if( m >= 0 && m <= 2 ){
                            printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
                            return 0;
                        }
                        else if( m >= 3 && m <= 5 ){
                            printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
                            return 0;
                        }
                        else if( m >= 6 && m <= 8 ){
                            printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
                            return 0;
                        }
                    }
                    else if((subgridValidate[currVal - 1] == 1) && (k >= 6 && k <=8)) {    // checks for dupes, segfaults if num > 9
                        if( m >= 0 && m <= 2 ){
                            printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
                            return 0;
                        }
                        else if( m >= 3 && m <= 5 ){
                            printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
                            return 0;
                        }
                        else if( m >= 6 && m <= 8 ){
                            printf("Row: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", k + 1);
                            return 0;
                        }
                    }
                    else //all subgrid have correct values.
                    {
                        return 1; // true
                    }
                }
            }
        }
    }
}

// Validating columns in the 3x3 grid *BACK UP*
// Fixing column tracking
// int validateCols(int x[9][9]) {
//     int col = 0;
//     // Traversing Rows
//     for(int i = 0; i < 9; i++) {
//         // Initialzing array to detect for duplicate values
//         int colValidate[9] = {0};
//         // Traversing columns
//         for(int j = 0; j < 9; j++) {
//             // Holds current value depending on row / col
//             int currVal = x[i][j];

//             // If the index is filled with a zero
//             // that means the index is not taken
//             if(colValidate[currVal - 1] == 0) {
//                 colValidate[currVal - 1] = 1;   // fill index with 1 (true)
//             } else {    // Checks if dupllicate or out of bounds
//                 printf("Column: %d does not have the required values\n", j + 1);
//                 return 0;
//             }
//         }   col ++;
//     }
// }

// Function to check 3x3 Sub-Grids
int validateCols(int x[9][9])
{
    for (int i = 0; i < 9; i += 3)
    {
        for (int j = 0; j < 9; j += 3)
        {
            int subgridValidate[9] = {0};

            for (int k = i; k < i + 3; k++)
            {
                for (int m = j; m < j + 3; m++)
                {
                    int currVal = x[k][m];
                    if (subgridValidate[currVal - 1] == 0)
                    {
                        subgridValidate[currVal - 1] = 1;
                    }
                    // else
                    // {
                    //     // printf("row: %d, col: %d", k+1, m+1);
                    //     // printf("Row: %d does not have required values \n", k + 1);
                    //     // printf("Column: %d does not have required values \n", m + 1);
                    //     return 0;
                    // }
                    else if((subgridValidate[currVal - 1] == 1) && (k >= 0 && k <=2)) {    // checks for dupes, segfaults if num > 9
                        if( m >= 0 && m <= 2 ){
                            printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
                            return 0;
                        }
                        else if ( m >= 3 && m <= 5 ){
                            printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
                            return 0;
                        }
                        else if ( m >= 6 && m <= 8 ){
                            printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
                            return 0;
                        }
                    }
                    else if((subgridValidate[currVal - 1] == 1) && (k >= 3 && k <=5) ) {    // checks for dupes, segfaults if num > 9
                        if( m >= 0 && m <= 2 ){
                            printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
                            return 0;
                        }
                        else if( m >= 3 && m <= 5 ){
                            printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
                            return 0;
                        }
                        else if( m >= 6 && m <= 8 ){
                            printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
                            return 0;
                        }
                    }
                    else if((subgridValidate[currVal - 1] == 1) && (k >= 6 && k <=8)) {    // checks for dupes, segfaults if num > 9
                        if( m >= 0 && m <= 2 ){
                            printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
                            return 0;
                        }
                        else if( m >= 3 && m <= 5 ){
                            printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
                            return 0;
                        }
                        else if( m >= 6 && m <= 8 ){
                            printf("Column: %d does not have required values (either a duplicate or value not in range of 1 - 9) \n", m + 1);
                            return 0;
                        }
                    }
                    else //all subgrid have correct values.
                    {
                        return 1; // true
                    }
                }
            }
        }
    }
}

// Needs intense fixing
int validateSubGrids(int x[9][9])
{
    for (int i = 0; i < 9; i += 3)
    {
        for (int j = 0; j < 9; j += 3)
        {
            int subgridValidate[9] = {0};

            for (int k = i; k < i + 3; k++)
            {
                for (int m = j; m < j + 3; m++)
                {
                    int currVal = x[k][m];
                    if (subgridValidate[currVal - 1] == 0)
                    {
                        subgridValidate[currVal - 1] = 1;
                    }
                    // else
                    // {
                    //     // printf("row: %d, col: %d", k+1, m+1);
                    //     // printf("Row: %d does not have required values \n", k + 1);
                    //     // printf("Column: %d does not have required values \n", m + 1);
                    //     return 0;
                    // }
                    else if((subgridValidate[currVal - 1] == 1) && (k >= 0 && k <=2)) {    // checks for dupes, segfaults if num > 9
                        if( m >= 0 && m <= 2 ){
                            printf("The top left subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
                            return 0;
                        }
                        else if ( m >= 3 && m <= 5 ){
                            printf("The top mid subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
                            return 0;
                        }
                        else if ( m >= 6 && m <= 8 ){
                            printf("The top right subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
                            return 0;
                        }
                    }
                    else if((subgridValidate[currVal - 1] == 1) && (k >= 3 && k <=5) ) {    // checks for dupes, segfaults if num > 9
                        if( m >= 0 && m <= 2 ){
                            printf("The left subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
                            return 0;
                        }
                        else if( m >= 3 && m <= 5 ){
                            printf("The left mid subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
                            return 0;
                        }
                        else if( m >= 6 && m <= 8 ){
                            printf("The left right subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
                            return 0;
                        }
                    }
                    else if((subgridValidate[currVal - 1] == 1) && (k >= 6 && k <=8)) {    // checks for dupes, segfaults if num > 9
                        if( m >= 0 && m <= 2 ){
                            printf("The bottom left subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
                            return 0;
                        }
                        else if( m >= 3 && m <= 5 ){
                            printf("The bottom mid subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
                            return 0;
                        }
                        else if( m >= 6 && m <= 8 ){
                            printf("The bottom right subgrid does not have the required values (either a duplicate or value not in range of 1 - 9)\n");
                            return 0;
                        }
                    }
                    else //all subgrid have correct values.
                    {
                        return 1; // true
                    }
                }
            }
        }
    }
}

void *vr(int x[9][9]) {
    validateRows(x);
}
void *vc(int x[9][9]) {
    validateCols(x);
}
void *vs(int x[9][9]) {
    validateSubGrids(x);
}

bool validSudokuGrid(int x[][9])
{
    int numThreads = 2;
    pthread_t tid [2];

    for(int i = 0; i < 1; i++) {
        if(i == 0) {
            pthread_create(&tid[i], NULL, vr(x), NULL);
        } else if(i == 1) {
            pthread_create(&tid[i], NULL, vc(x), NULL);
        } else {
            pthread_create(&tid[i], NULL, vc(x), NULL);
        }
        printf("OOOGA BOOGA");
    }
    printf("OOOGA BOOGA");
    for (int i = 0; i < numThreads; i++) {
    pthread_join(tid[i], NULL);
    printf("Thread %10x joined\n", tid[i]);
    fflush(stdout);
}

    printf("All Four Threads have exited using join(), exiting program....\n");
    fflush(stdout);
    exit(EXIT_SUCCESS);

    return validateRows(x) + validateCols(x) + validateSubGrids(x); // if all true = valid 9x9, else = not valid 9x9
    // return validateSubGrids(x);
}

Pthreads 需要 void* func (void*) 形式的回调函数,句号。您不能发明自己的函数格式并期望它起作用。

此外 vr(x) 等参数是 函数调用 - 你调用函数一次然后使用它的结果告诉 pthread_create 它是一个指针到回调函数,它不是 - 这只是胡说八道。

此外,具有 return 类型的函数必须始终 return 某些内容。

所有这些问题都可以通过正确配置编译器在早期避免,因此它会在遇到明显的错误和无效的 C 时给出错误,请参阅 What compiler options are recommended for beginners learning C? 正确使用函数是非常基础的东西,你在进入更高级的主题之前需要掌握,例如 multi-threading.

正确使用,正如友情所说 man:

void* vr (void* x) {
    validateRows(x);
    return NULL;
}

...

pthread_create(&tid[i], NULL, vr, x);

我不确定你的代码是否编译,但如果编译成功,那么会发生什么:当程序 运行s,然后在 pthread_create() 函数中,它将调用你的函数vr() 并使用 vr() 的 return 值作为指向创建线程时应调用的函数的指针。

但是vr()没有return任何值,但在这里并不重要。

任何函数的return值根据系统存储在某处(寄存器等)。假设 return 值存储在名为 A 的寄存器中。因此,将调用 vr(x),然后读取寄存器 A 中的值,然后代码将假定该值是指向应该调用的函数。但是 A 可以有任何值(因为函数 vr(x) 没有 return 任何值,因此它没有更新 A)- 0x0、0x1、0x75745 等。而且大多数情况下这将是一个无效地址(可能会指向受限内存区域,或只读内存等)因此硬件会引发内存访问冲突 interrupt/signal,然后导致分段错误。

运行下面的代码你就明白我在说什么了


#include <stdio.h>
#include <pthread.h>

void *f(void *g)
{
    printf("Called f().\n");
}

void *x(void *v)
{
    printf("Called x().\n");
    return (void *)(f);
}

int main(void)
{

    pthread_t pt;

    pthread_create(&pt, NULL, x((void *)5), NULL);

    // join pthread.
    pthread_join(pt, NULL);

    return 0;

}

当您 运行 上面的代码时,函数 x() 和 f() 都会被调用。

输出将是:

调用了 x()。 调用了 f()。