I'm working on a small program of multithreaded matrix multiplication. My first job is to fill the entry of matrices with a random integer. I met some segment faults after I tried to pass a function pointer to pthread_create. And I think the problem is in function pthread_join.
But there are two issues in general.
The first one is the segment fault does not happen every time. Sometimes the code works, but most of the times it doesn't. So it really confuses me.
The other one is when the code is working, there are always several entries still not initialized, especially for matrix[0][0], it is never initialized. And I don't quite know where to debug that one.
Here's my code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#define N 5
#define MAX 10
int A[N][N];
int B[N][N];
int C[N][N];
pthread_t pid[N][N];
typedef struct {
int row, col;
} Pos;
typedef void* (*thread_func)(void*);
void print_matrix(int M[][N]) {
int i, j;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
printf("%3d", M[i][j]);
if (j < N - 1) {
printf(", ");
}
}
printf("\n");
}
}
void join_threads(void) {
int i, j;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
pthread_join(pid[i][j], NULL);
}
}
}
void* fill_entry(void* arg) {
Pos* pos = (Pos*)arg;
A[pos->row][pos->col] = rand() % MAX;
B[pos->row][pos->col] = rand() % MAX;
return NULL;
}
void dispatch_jobs(thread_func job_func) {
int i, j;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
Pos pos;
pos.row = i;
pos.col = j;
if (pthread_create(&pid[i][j], NULL, job_func, (void*)&pos)) {
perror("pthread_create");
exit(-1);
}
}
}
}
int main(void) {
srand(time(NULL));
dispatch_jobs(&fill_entry);
join_threads();
printf("Matrix A:\n");
print_matrix(A);
printf("Matrix B:\n");
print_matrix(B);
return 0;
}
Pos pos;
pos.row = i;
pos.col = j;
if (pthread_create(&pid[i][j], NULL, job_func, (void*)&pos)) {
perror("pthread_create");
exit(-1);
}
You are passing a pointer to a local variable to the threads. Once the thread tries to access the data, i.e. dereferences the pointer, the variable is long gone, reused, and contains garbage data.
Related
I have an array
arr[]={7,5,-8,3,4};
And I have to update the same array to
arr[]={7,12,4,7,11};
my code:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int sumArr(int *arr, int size);
void main()
{
int arr[] = { 7,5,-8,3,4 };
int i, size, res = 0;
printf("Enter Size Of The Array:");
scanf("%d", &size);
res = sumArr(arr, size);
for (i = 0; i < size; i++)
{
printf("%d\n", res);
}
}
int sumArr(int *arr, int size)
{
int i;
for (i = 0; i < size; i++)
{
arr[i+1]+= arr[i];
printf(" %d \n", arr[i + 1]);
}
return arr[i+1];
}
The output should be: 7,12,4,7,11
But in my code, the output is: 12,4,7,11,-858993449,58196502,58196502,58196502,58196502,58196502
Any hints?
I can use auxiliary functions for input and output arrays, will it help?
You have several mistakes in your code:
You need to stop the summing loop once i+1 reaches the end of the array
Your code knows the size; there is no need to read it from end-user
You need to print the value of res once, rather than printing it in a loop
You should consider moving the printing portion of the program into main from sumArray.
The modifications are very straightforward:
int sumArr(int *arr, int size) {
// Stop when i+1 reaches size; no printing
for (int i = 0; i+1 < size; i++) {
arr[i+1]+= arr[i];
}
return arr[size-1];
}
Printing in the main:
printf("sum=%d\n", res);
for (int i = 0; i < size; i++) {
printf("arr[%d] = %d\n", i, arr[i]);
}
Demo.
I'm working on a project that requires somewhat similar functionality to the program below so I've tried to create a simpler program to debug my larger program. The threads I'm creating are returning values that are inconsistent with their expected output but their return values are not random. It almost seems like the threads are returning the values from other threads or that the variable they are returned to ("tmp") is updating.
The expected output should be...
0 1
1 2
#include <stdio.h>
#include <pthread.h>
struct Numbers {
int x;
int y;
};
void *go(void* param)
{
struct Numbers* nums = (struct Numbers*) param;
int sum = nums -> x + nums -> y;
return (void*) sum;
}
int main()
{
int result[2][2];
int tmp;
pthread_t thread[2][2];
int i, j;
for(i=0;i<2;i++)
{
for(j=0;j<2;j++)
{
struct Numbers nums;
nums.x = i;
nums.y = j;
pthread_create(&thread[i][j], NULL, go, &nums);
}
}
for(i=0;i<2;i++)
{
for(j=0;j<2;j++)
{
pthread_join(thread[i][j], (void*) &tmp);
result[i][j] = tmp;
}
}
for(i=0;i<2;i++)
{
for(j=0;j<2;j++)
{
printf("%d\t", result[i][j]);
}
printf("\n");
}
return 0;
}
You're passing the address of a variable that probably won't exist once the thread begins executing, or at least will be seen by multiple threads, or is a data race as one thread writes it while the others read it.
A general solution is to dynamically allocate both the arguments and results of your thread, and let the caller and thread communicate that way.
Example:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
struct threadargs {
int x;
int y;
};
struct threadresults {
int sum;
int product;
};
void* threadfunc(void* args_void) {
// Get thread args in usable type.
struct threadargs* args = args_void;
struct threadresults* results = NULL;
//Compute.
int sum = args->x + args->y;
int product = args->x * args->y;
// Return the result.
results = malloc(sizeof(*results));
results->sum = sum;
results->product = product;
free(args);
return results;
}
int main()
{
pthread_t thread[2][2];
struct threadresults* results[2][2] = {0};
int i, j;
for (i = 0;i < 2; ++i) {
for (j = 0; j < 2; ++j) {
struct threadargs* args = malloc(sizeof(*args));
args->x = i;
args->y = j;
pthread_create(&thread[i][j], NULL, threadfunc, args);
}
}
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
void* result;
pthread_join(thread[i][j], &result);
results[i][j] = result;
}
}
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
printf("sum: %d\tproduct: %d\n",
results[i][j]->sum, results[i][j]->product);
}
}
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
free(results[i][j]);
}
}
return 0;
}
I am trying to create a structure that will have two integer values, an array, and two 2-D matrices using my code below. I can initialize the structure with the integers and array just fine, and my 'Gen' function will create the random values I want for the array.
However, when I try adding in the matrix components, I run into a problem. My compiler gives me a warning: "initialization from incompatible pointer type". If I understand what I have read so far, this is because the structure needs to be pointed to an array of pointers that represent each row in the matrix. I don't know the syntax for that.
A quick note: the other topics I've seen that are related to this issue all initialize the structure in a function other than the main() function, so I haven't found those solutions helpful.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <string.h>
// Define structure
typedef struct {
int row;
int col;
int *arr;
int **mat1;
int **mat2;
}container;
// Function headers
void Gen(container Thing);
int main() {
int row = 5;
int col = 6;
int A[row];
int M1[row][col];
int M2[row][col+1];
// Initialize structure
container Object = {row, col, A, M1, M2};
// Run "Gen" function
Gen(Object);
int i, j; // Index variables
// Display the array
for(i = 0; i < row; i++)
{
printf("%i ", Object.arr[i]);
}
printf("\n\n");
// Display the numbers from the matrices
for(j = 0; j < Object.row; j++)
{
for(i = 0; i < Object.col; i++)
{
printf("%i ", Object.mat1[j][i]);
}
printf("\n");
}
printf("\n");
for(j = 0; j < Object.row; j++)
{
for(i = 0; i < Object.col; i++)
{
printf("%i ", Object.mat2[j][i]);
}
printf("\n");
}
return (EXIT_SUCCESS);
}
// Function to generate random values in the array & matrices
void Gen(container Thing)
{
int i, j;
srand(time(NULL));
// Generate random values for the array
for(i = 0; i < Thing.row; i++)
{
Thing.arr[i] = rand() % 5;
}
// Generate random values for the matrix
for(j = 0; j < Thing.row; j++)
{
for(i = 0; i < Thing.col; i++)
{
Thing.mat1[j][i] = rand() % 5;
Thing.mat2[j][i] = rand() % 5;
}
}
} // End of "Gen" function
container Object = {row, col, A, M1, M2};
is wrong since the type of M1 is int[row][col], which can decay to int (*)[col] but not to int**. You have the same problem with M2.
You'll need to rethink your strategy for generating a container.
For example:
int main() {
int row = 5;
int col = 6;
int A[row];
int* M1[row];
int* M2[row];
for ( int i = 0; i < row; ++i )
{
M1[i] = malloc(sizeof(M1[i][0])*col);
M2[i] = malloc(sizeof(M1[i][0])*(col+1));
}
// Initialize structure
container Object = {row, col, A, M1, M2};
...
for ( int i = 0; i < row; ++i )
{
free(M1[i]);
free(M2[i]);
}
return (EXIT_SUCCESS);
}
I want to create a function called get_lotto_draw that will create an array of 6 random numbers and return them to main.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
get_lotto_draw()
{
int lottery[50];
int u,i,j,temp;
int lotto[6];
srand(time(NULL));
for (i =0; i<49; i++)
lottery[i] = i+1;
for (i =0; i<49; i++)
{
j = (rand()%49)+1;
temp = lottery[i];
lottery[i] = lottery[j];
lottery[j] = temp;
}
for (i =0; i<6; i++)
{
lotto[i] = lottery[i];
}
return lotto;
}
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void get_lotto_draw(int lotto[])
{
int lottery[50];
int u,i,j,temp;
for (i =0; i<49; i++)
lottery[i] = i+1;
for (i =0; i<49; i++)
{
j = (rand()%49)+1;
temp = lottery[i];
lottery[i] = lottery[j];
lottery[j] = temp;
}
for (i =0; i<6; i++)
{
lotto[i] = lottery[i];
}
return ;
}
int _tmain(int argc, _TCHAR* argv[])
{
int lotto[6];
srand(time(NULL));
get_lotto_draw(lotto);
for (int i = 0; i < 6; i ++)
printf ("%d ", lotto[i]);
printf ("\n");
return 0;
}
The function get_lotto_draw will take the array 'lotto' as an argument - unsized array.
If you declare lotto as auto variable inside the function then when the function ends - the auto variable lotto would have been removed - check this link for details.
So you declare lotto in main and pass it to the function.
Other options include
use malloc (to allocate memory for 'lotto') inside the get_lotto_draw and free in main (unless you are very careful- this will lead to memory leaks - I do not recommend this)
use malloc in main and pass the allocated memory to the function and free it in main later
create a static and use it.
My recommendation is in such situations to use the stack (auto variable as used above) otherwise use malloc/free.
I fixed some of the bugs others pointed out
Thank you very much for everyone who helped. I spent a few hours reading and learning about the things you mentioned. I have now managed to create a piece of code that will do what I wanted.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int *get_lotto_draw(int n)
{
int i;
int *lotto;
lotto = malloc(n * sizeof(*lotto));
if (lotto == NULL)
return NULL;
int lottery[50];
int u,j,temp;
for (i =0; i<49; i++)
lottery[i] = i+1;
for (i =0; i<49; i++)
{
j = (rand()%49)+1;
temp = lottery[i];
lottery[i] = lottery[j];
lottery[j] = temp;
}
for (i =0; i<6; i++)
{
lotto[i] = lottery[i];
}
return lotto;
}
int main(int argc, char *argv[])
{
int i, n = 6;
int *lotto;
srand(time(NULL));
lotto = get_lotto_draw(n);
if (lotto == NULL)
return -1;
printf("Here is the array: ");
for(i = 0 ; i < n ; i++) {
printf("%d ", lotto[i]);
}
free(lotto);
printf("\n\n");
return 0;
}
I also found that I can do this by using static int as I have an array of set length.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int *get_lotto_draw(int n)
{
int i;
static int lotto[6];
int lottery[50];
int u,j,temp;
for (i =0; i<49; i++)
lottery[i] = i+1;
for (i =0; i<49; i++)
{
j = (rand()%49)+1;
temp = lottery[i];
lottery[i] = lottery[j];
lottery[j] = temp;
}
for (i =0; i<6; i++)
{
lotto[i] = lottery[i];
}
return lotto;
}
int main(int argc, char *argv[])
{
int i, n = 6;
int *lotto;
srand(time(NULL));
lotto = get_lotto_draw(n);
printf("Here is the array: ");
for(i = 0 ; i < n ; i++) {
printf("%d ", lotto[i]);
}
printf("\n\n");
return 0;
}
This code below is the code for finding the determinant for 3x3 matrix (this code is intended for nxn matrix, but for the sample, I used 3x3), using recursive
The result is working fine, but I wonder what errors in this code make this must be the printf("\n") before calling the sub-function (itself) or else it will return the error 0xc0000fd (stack overflow).
#include "stdio.h"
#include "stdlib.h"
#include "conio.h"
#define size 3
void trimarray(int**rrayrc,int**rrayout, int dim,int cuti,int cutj)
{
int i, j;
int ti = 0,tj;
for(i = 0; i<dim; i++)
{
tj = 0;
for(j = 0; j< dim; j++)
{
if(!((i==cuti)||(j==cutj)))
{
rrayout[ti][tj] = rrayrc[i][j];
}
if(j!=cutj) {tj++;}
}
if(i!=cuti) {ti++;}
}
}
void initializearray(int** rray,int dim)
{
int i, j;
for(i = 0; i<dim; i++)
{
for(j = 0; j<dim; j++)
{
rray[i][j] = 0;
}
}
}
int det(int** rray, int dim)
{
int i,j;
int cut[dim-1][dim-1];
int* cutp[i];
int mul = 1,sum=0;
if(dim >1)
{
for(i = 0; i<dim-1; i++)
{
cutp[i] = cut[i];
}
initializearray(cutp,dim-1);
for(i = 0; i<dim; i++)
{
printf("\n",dim); //<< Without this the program won't work
trimarray(rray,cutp,dim,0,i);
sum+=det(cutp,dim-1)*mul*rray[0][i];
mul = 0-mul;
}
return sum;
}
else
{
return rray[0][0];
}
}
int main()
{
int test[size][size] = {2,-3,-2,-6,3,3,-2,-3,-2};
int* testpntr[size];
int i,deter;
for(i = 0; i<size; i++)
{
testpntr[i] = test[i];
}
deter = det(testpntr,size);
printf("[%d]",deter);
getch();
return 0;
}
The answers will be dearly appreciated.
int* cutp[i]; is undefined behavior since i is uninitialized at this stage. You have no idea what is the size of cutp array.