为什么我总是出现分段错误?

问题描述 投票:0回答:1

我正在尝试制作一个数独验证器作为 C 上的多线程示例,其中 3 个并发线程检查数独中的行、列和网格,并告诉数独是否有效,但我似乎遇到了分段错误每次我运行它。

#include <stdio.h>
#include <pthread.h>
#include <stdbool.h>
#include <unistd.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>

#define MAX_ROWS_COLS 100

int rows;
int cols;

typedef struct {
    int (*array)[MAX_ROWS_COLS];
    int rows;
    int cols;
} ThreadArgs;


bool checkRows(void* arg){
    ThreadArgs* threadArgs = (ThreadArgs*)arg;
    int (*array)[threadArgs->cols] = threadArgs->array;
    int rows = threadArgs->rows;
    int cols = threadArgs->cols;
    
    bool used[rows];
    for(int i = 0; i < rows; i++){
        used[i] = false;
    } 
    
    for(int i = 0; i < rows; i++){
        for(int j = 0; j < cols; j++){
            int num = array[i][j];
            if(num < 1 || num > rows || used[num-1]){
                return false;
            }
            used[num-1] = true;
        }
        for(int k = 0 ; k < rows; k++){
            used[k] = false;
        }
    }
    return true;
}

bool checkCols(void* arg){
    ThreadArgs* threadArgs = (ThreadArgs*)arg;
    int (*array)[threadArgs->cols] = threadArgs->array;
    int rows = threadArgs->rows;
    int cols = threadArgs->cols;

    bool used[rows];
    for(int i = 0; i < rows; i++){
        used[i] = false;
    } 
    
    for(int i = 0; i < rows; i++){
        for(int j = 0; j < cols; j++){
            int num = array[j][i];
            if(num < 1 || num > rows || used[num-1]){
                return false;
            }
            used[num-1] = true;
        }
        for(int k = 0 ; k < rows; k++){
            used[k] = false;
        }
    }
    return true;
}

int checkGrid(void* arg){
    ThreadArgs* threadArgs = (ThreadArgs*)arg;
    int (*array)[threadArgs->cols] = threadArgs->array;
    int rows = threadArgs->rows;
    int cols = threadArgs->cols;
    
    bool used[rows];
    for(int i = 0; i < rows; i++){
        used[i] = false;
    }
    //Check grid
    int grid = sqrt(rows);
    int count = 0;
    for(int i = 0; i < rows; i=i+grid){
        for(int j = 0; j < rows; j = j+grid){
            for(int k = 0; k < grid; k++){
                for(int l = 0; l < grid; l++){
                    //printf("%d,%d\n",i+k,j+l);
                    int num = array[i+k][j+l];
                    if(num < 1 || num > rows || used[num-1]){
                        return false;
                    }
                    used[num-1] = true;
                }
                for(int m = 0; m < rows; m++){
                    used[m] = false;
                }
            }
        }
    }
    return true;
}

bool checkSudoku(int array[rows][cols]){
    pthread_t p1,p2,p3;
    int rowResult, colResult, gridResult;

    ThreadArgs args = {array, rows, cols};

    pthread_create(&p1, NULL, checkRows, (void*)&args);
    pthread_create(&p2, NULL, checkCols, (void*)&args);
    pthread_create(&p3, NULL, checkGrid, (void*)&args);

    pthread_join(p1, (void**)&rowResult);
    pthread_join(p2, (void**)&colResult);
    pthread_join(p3, (void**)&gridResult);

    if(rowResult == 0 || colResult == 0 || gridResult == 0){
        return false;
    }
    return true;
}


int main() {
    clock_t start, end;
    double cpu_time_used;

    start = clock();
    FILE *file;
    char line[1000];

    // Open the LaTeX file
    file = fopen("input.tex", "r");
    if (file == NULL) {
        printf("Error opening file.\n");
        return 1;
    }

    if (fgets(line, sizeof(line), file)) {
        sscanf(line, "%d %d", &rows, &cols);
    } else {
        printf("Error reading dimensions.\n");
        fclose(file);
        return 1;
    }

    int **array = (int **)malloc(rows * sizeof(int *));
    if (array == NULL) {
        printf("Error allocating memory for array.\n");
        return 1;
    }
    for (int i = 0; i < rows; i++) {
        array[i] = (int *)malloc(cols * sizeof(int));
        if (array[i] == NULL) {
            printf("Error allocating memory for array.\n");
            return 1;
        }
    }

    for (int i = 0; i < rows; i++) {
        if (fgets(line, sizeof(line), file)) {
            char *token = strtok(line, " ");
            for (int j = 0; j < cols && token != NULL; j++) {
            array[i][j] = atoi(token);
            token = strtok(NULL, " ");
        }
        } else {
            printf("Error reading array values.\n");
            fclose(file);
            return 1;
        }
    }

    fclose(file);

    printf("Populated 2D array:\n");
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                printf("%d ", array[i][j]);
            }
        printf("\n");
    }
    
    if(checkSudoku(array)){
        printf("Sudoku valid\n");
    } else {
        printf("Invalid\n");
    }
    
    end = clock();
    cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
    double microseconds = cpu_time_used * 1000000;

        printf("Execution time: %.2f microseconds\n", microseconds);

    // Free dynamically allocated memory
    for (int i = 0; i < rows; i++) {
        free(array[i]);
    }
    free(array);
    
    return 0;
}

如果重要的话,我会在分配有 4 个线程的 Kali Linux VM 上运行它。

它应该等待 3 个线程终止,然后如果数独有效则返回。

c multithreading segmentation-fault pthreads
1个回答
0
投票

此代码存在多个问题:

  • 过度赋予线程的函数只能返回
    void*
    而不是
    bool
    (但你可以使用
    pthread_exit((void*)true)
  • int** array
    int *array[MAX_ROWS_COLS]
    不同,因此您不能将
    int** array
    过度赋予接受
    int *array[MAX_ROWS_COLS]
  • 的函数
  • 另一个问题是您在全局范围内使用变量
    cols
    rows
    ,但也在局部范围内使用(在这种情况下可以,但你应该避免它)
  • 缺少头文件
    string.h
#include <math.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#define MAX_ROWS_COLS 100

int rows;
int cols;

typedef struct {
    int** array;
    int rows;
    int cols;
} ThreadArgs;

void* checkRows(void* arg) {
    ThreadArgs* threadArgs = (ThreadArgs*)arg;
    int** array = threadArgs->array;
    int rows = threadArgs->rows;
    int cols = threadArgs->cols;

    bool used[rows];
    for (int i = 0; i < rows; i++) {
        used[i] = false;
    }

    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            int num = array[i][j];
            if (num < 1 || num > rows || used[num - 1]) {
                pthread_exit((void*)false);
            }
            used[num - 1] = true;
        }
        for (int k = 0; k < rows; k++) {
            used[k] = false;
        }
    }
    pthread_exit((void*)true);
}

void* checkCols(void* arg) {
    ThreadArgs* threadArgs = (ThreadArgs*)arg;
    int** array = threadArgs->array;
    int rows = threadArgs->rows;
    int cols = threadArgs->cols;

    bool used[rows];
    for (int i = 0; i < rows; i++) {
        used[i] = false;
    }

    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            int num = array[j][i];
            if (num < 1 || num > rows || used[num - 1]) {
                pthread_exit((void*)false);
            }
            used[num - 1] = true;
        }
        for (int k = 0; k < rows; k++) {
            used[k] = false;
        }
    }
    pthread_exit((void*)true);
}

void* checkGrid(void* arg) {
    ThreadArgs* threadArgs = (ThreadArgs*)arg;
    int** array = threadArgs->array;
    int rows = threadArgs->rows;
    int cols = threadArgs->cols;

    bool used[rows];
    for (int i = 0; i < rows; i++) {
        used[i] = false;
    }

    // Check grid
    int grid = sqrt(rows);
    int count = 0;
    for (int i = 0; i < rows; i = i + grid) {
        for (int j = 0; j < rows; j = j + grid) {
            for (int k = 0; k < grid; k++) {
                for (int l = 0; l < grid; l++) {
                    // printf("%d,%d\n",i+k,j+l);
                    int num = array[i + k][j + l];
                    if (num < 1 || num > rows || used[num - 1]) {
                        pthread_exit((void*)false);
                    }
                    used[num - 1] = true;
                }
                for (int m = 0; m < rows; m++) {
                    used[m] = false;
                }
            }
        }
    }
    pthread_exit((void*)true);
}

bool checkSudoku(int** array) {
    pthread_t p1, p2, p3;
    void *rowResult, *colResult, *gridResult;

    ThreadArgs args = {array, rows, cols};

    pthread_create(&p1, NULL, checkRows, (void*)&args);
    pthread_create(&p2, NULL, checkCols, (void*)&args);
    pthread_create(&p3, NULL, checkGrid, (void*)&args);

    pthread_join(p1, &rowResult);
    pthread_join(p2, &colResult);
    pthread_join(p3, &gridResult);

    if ((bool)rowResult == 0 || (bool)colResult == 0 || (bool)gridResult == 0) {
        return false;
    }

    return true;
}

int main() {
    clock_t start, end;
    double cpu_time_used;

    start = clock();
    FILE* file;
    char line[1000];

    // Open the LaTeX file
    file = fopen("input.tex", "r");
    if (file == NULL) {
        printf("Error opening file.\n");
        return 1;
    }

    if (fgets(line, sizeof(line), file)) {
        sscanf(line, "%d %d", &rows, &cols);
    } else {
        printf("Error reading dimensions.\n");
        fclose(file);
        return 1;
    }

    int** array = (int**)malloc(rows * sizeof(int*));
    if (array == NULL) {
        printf("Error allocating memory for array.\n");
        return 1;
    }
    for (int i = 0; i < rows; i++) {
        array[i] = (int*)malloc(cols * sizeof(int));
        if (array[i] == NULL) {
            printf("Error allocating memory for array.\n");
            return 1;
        }
    }

    for (int i = 0; i < rows; i++) {
        if (fgets(line, sizeof(line), file)) {
            char* token = strtok(line, " ");
            for (int j = 0; j < cols && token != NULL; j++) {
                array[i][j] = atoi(token);
                token = strtok(NULL, " ");
            }
        } else {
            printf("Error reading array values.\n");
            fclose(file);
            return 1;
        }
    }

    fclose(file);

    printf("Populated 2D array:\n");
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            printf("%d ", array[i][j]);
        }
        printf("\n");
    }

    if (checkSudoku(array)) {
        printf("Sudoku valid\n");
    } else {
        printf("Invalid\n");
    }

    end = clock();
    cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
    double microseconds = cpu_time_used * 1000000;

    printf("Execution time: %.2f microseconds\n", microseconds);

    // Free dynamically allocated memory
    for (int i = 0; i < rows; i++) {
        free(array[i]);
    }
    free(array);

    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.