我正在尝试制作一个数独验证器作为 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 个线程终止,然后如果数独有效则返回。
此代码存在多个问题:
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;
}