使用 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);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Pthreads 需要一个
void* func (void*)
, period 形式的回调函数。您不能发明自己的函数格式并期望它能够工作。此外,vr(x) 等参数是函数调用 - 您调用该函数一次,然后使用其结果告诉 pthread_create 它是一个指向回调函数的指针,但它不是——这只是废话。
此外,具有返回类型的函数必须始终
返回
某些内容。所有这些问题都可以通过正确配置编译器来尽早避免,以便在遇到明显的错误和无效的 C 时给出错误,请参阅 为学习 C 的初学者推荐哪些编译器选项? 正确使用函数是非常基础的东西,也是您在继续学习多线程等更高级主题之前需要掌握的东西。
正确使用,正如友好的 man 中所述:
Pthreads expect a callback function of the form
void* func (void*)
, period. You cannot invent your own function format and expect it to work.Furthermore the
vr(x)
etc parameters are function calls - you call the function once then use the result of that to tellpthread_create
that it's a pointer to a callback function, which it isn't - it's just nonsense.Also a function with a return type must always
return
something.All of these problems could be avoided early on by configuring the compiler correctly, so that it gives errors upon encountering blatant bugs and invalid C, see What compiler options are recommended for beginners learning C? Correct use of functions is very fundamental stuff and something you need to grasp before moving on to more advanced topics like multi-threading.
Correct use, as was told in the friendly man:
我不确定你的代码是否可以编译,但如果可以的话,会发生什么:当程序运行时,在 pthread_create() 函数中,它将调用你的函数 vr() 并使用 vr() 的返回值作为指向创建线程时应调用的函数的指针。
但 vr() 不返回任何值,但在这里没有意义。
任何函数的返回值都根据系统存储在某个地方(寄存器等)。假设返回值存储在名为 A 的寄存器中。因此,将调用 vr(x),然后读取寄存器 A 中的值,然后代码将假设该值是指向应该执行的函数的指针。称为。但是 A 可以有任何值(因为函数 vr(x) 不返回任何值,因此它没有更新 A) - 0x0、0x1、0x75745 等。大多数情况下,这将是一个无效地址(可能是它)将指向受限制的内存区域,或只读内存等),因此硬件将引发内存访问冲突中断/信号,从而导致分段错误。
运行下面的代码你就会明白我在说什么。
当您运行上面的代码时,函数 x() 和 f() 都会被调用。
输出将是:
称为 x()。
称为 f()。
I am not sure if your code compiles but if it does then what will happen is this: When the program runs, then in pthread_create() function, it will call your function vr() and use the return value of vr() as the pointer to the function that should be called when the thread is created.
But vr() does not return any value but it is not of significance here.
The return value of any function is stored somewhere (register, etc.) according to the system. Let's assume that the return value is stored in a register called A. So, vr(x) will be called and then the value in register A will be read and the code will then assume that this value is the pointer to the function that should be called. But A can have any value (because the function vr(x) doesn't return any value and hence it didn't update A) - 0x0, 0x1, 0x75745, etc. And mostly this will be an invalid address (may be it will point to a restricted memory area, or to read only memory, etc.) and so the hardware will raise a memory access violation interrupt/signal which then results in segmentation fault.
Run the following code and you will understand what I am saying.
Both functions x() and f() will get called when you run the above code.
The output will be:
Called x().
Called f().