我正在try 在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;
}

如果重要的话,我在Kali Linux VM上运行这个,分配了4个线程.

它应该等待3个线程终止,然后在数独有效的情况下返回.

推荐答案

此代码存在多个问题:

  • 传递给线程的函数只能返回void*,而不能返回bool(但您可以使用pthread_exit((void*)true))
  • int** arrayint *array[MAX_ROWS_COLS]是不同的,因此不能将int** array赋给接受int *array[MAX_ROWS_COLS]的函数
  • 另一个问题是,您在全局范围内使用变量colsrows,在局部范围内也使用变量colsrows(在本例中是可以的,但您应该避免使用)
  • 缺少标题文件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;
}

C++相关问答推荐

在Windows上构建无聊的SSL x64

从STdin读写超过4096个字节

ATmega328P USART发送字符重复打印

编译SDL 2时缺少SDL_ttf

如何在IF语句中正确使用0.0

Win32API Wizzard97 PropSheet_SetWizButton不工作

Ruby C Api处理异常

使用sscanf获取零个或多个长度的字符串

为什么我会收到释放后堆使用错误?

对重叠字符串使用MemMove

为什么Fread()函数会读取内容,然后光标会跳到随机位置?

-Wnonnull-Compare警告不是具有误导性吗?

为什么这个分配做得不好呢?

如何使用空元素块声明指针数组

在运行时判断C/C++指针是否指向只读内存(在Linux操作系统中)

如何修复我的qsort()算法?它每次都给出不同的结果

生成一个半RNG,结果用C表示(无随机/随机)

使用mmap为N整数分配内存

C中2个数字的加法 - 简单的人类方法

初始化动态分配的布尔二维数组的最佳方法是什么?