Thread access static variable cause segmentation error [duplicate] - c

This question already has answers here:
initializing a static variable in header
(4 answers)
Closed 5 years ago.
I'm trying to compare performance of methods about adding two matrix.
one method is just to add.
the other method is to use threads.
but I have a trouble about segmentation error when a thread access a static variable!
Here is my code.
main.c
#include "matrixProcessor.h"
void main()
{
time_t s0, e0;
int i;
int status;
inputVec1 = (int*)malloc(sizeof(int)*(SIZE*SIZE));
inputVec2 = (int*)malloc(sizeof(int)*(SIZE*SIZE));
outputVec = (int*)malloc(sizeof(int)*(SIZE*SIZE));
srand(time(NULL));
initializeVector(inputVec1);
initializeVector(inputVec2);
//printf("=== INPUT VECTOR 1 ===\n");
//printVector(inputVec1);
//printf("=== INPUT VECTOR 1===\n");
//printVector(inputVec2);
//s0 = clock();
//addVec(inputVec1, inputVec2, outputVec);
//e0 = clock();
//printf("Basic Method Time : %f (s)\n",(double)(e0-s0)/CLOCKS_PER_SEC);
s0 = clock();
for(i = 0; i < NUM_THREAD; i++)
{
printf("%d-Thread Call\n",i);
pthread_create(&tid[i], NULL, &addProc, (void*)&i);
sleep(1);
}
e0 = clock();
printf("=== OUTPUT VECTOR===\n");
printVector(outputVec);
printf("Thread Method Time : %f (s)\n",(double)(e0-s0)/CLOCKS_PER_SEC);
free(inputVec1);
free(inputVec2);
free(outputVec);
}
matrixProcessor.c
#include "matrixProcessor.h"
void initializeVector(int* matPtr)
{
int i = 0;
for(i = 0; i < SIZE*SIZE ; i++)
{
matPtr[i] = rand()%100;
}
}
void addVec(int* inputVec1, int* inputVec2, int* outputVec)
{
int i = 0;
for(i = 0; i < SIZE * SIZE; i++)
{
outputVec[i] = inputVec1[i] + inputVec2[i];
}
}
void* addProc(void *p)
{
int* idx = (int*)p;
int count = (SIZE * SIZE) / NUM_THREAD;
int i;
printf("idx value : %d\n",*idx);
printf("Test : %d ", inputVec1[0]);
for(i = (*idx) * count ; i < (*idx)*count + count; i++)
{
outputVec[i] = inputVec1[i] + inputVec2[i];
}
return NULL;
}
void printVector(int* vec)
{
int i = 0;
int j = 0;
for(i = 0; i < SIZE ; i++)
{
for(j = 0; j < SIZE; j++)
{
printf("%d\t", vec[SIZE * i + j]);
}
printf("\n");
}
}
matrixProcessor.h
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>
#define SIZE 10
#define NUM_THREAD 10
pthread_t tid[NUM_THREAD];
static int* inputVec1;
static int* inputVec2;
static int* outputVec;
void initializeVector(int* matPtr);
void printVector(int* vec);
void addVec(int* inputVec1, int* inputVec2, int* outputVec);
void* addProc(void *p);
when compiling, i use -static - lpthread options.
I'm sure that accessing static variable cause segmentation error,
because this program prints some messages before reaching a code line which access static variable.
Here is result.
0-Thread Call
idx value : 0
Segmentation Error! ./main
Please someone help me..!

There are multiple problems in your code. The two that jump right out to me are listed below.
First, this one:
pthread_create(&tid[i], NULL, &addProc, (void*)&i);
What's the value of i when the child thread accesses it? It can be anything, because it changes as the main thread spawns more threads and continues to run.
Second, what do you think these free() statements do when they're executed while the child threads are still running:
free(inputVec1);
free(inputVec2);
free(outputVec);
When your code makes those calls, the child threads are still running since you don't call pthread_join() to make sure they've all completed.
You likely get the segmentation violation because your threads are accessing free()'d memory.

Related

Multithreading but first few threads are being skipped

It's been a few hours and i can't seem to understand the issue. Build this program to count from 1 - 10. The goal of this program is to use multithreading and dynamically split the array depending on how many threads it requested. Problem is the first 2 threads are being skipped and the last thread is doing most of th e process. I suspect it's the for loop that creates the threads.
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
typedef struct
{
int *array;
int batch;
int start;
int end;
} Parameter;
void *method(void *p)
{
Parameter *param = (Parameter *)p;
for (int i = param->start; i < param->end; i++)
{
printf("Start:%d\tEnd:%d\tIndex:%d\tValue:%d\n", param->start, param->end, i,param->array[i]);
}
}
int main(int argc, char **argv)
{
// Getting the user input
int array_length = atoi(argv[1]);
int batches = atoi(argv[2]);
printf("User specified Array:%d\tBatch:%d\n", array_length, batches);
// Creating an array
int *array = (int *)calloc(array_length, sizeof(int));
// Fill it up with some data
for (int i = 0; i < array_length; i++)
{
array[i] = i;
}
// Determine the Batches
int batch_size = array_length / batches;
int remainder = array_length % batches;
printf("%d\n", batch_size);
printf("%d\n", remainder);
int start = 0;
int end = 0;
int index =0;
// List of parameters
Parameter *param = (Parameter *)calloc(batches, sizeof(Parameter));
pthread_t *threads = (pthread_t *)calloc(batches, sizeof(pthread_t));
// Loop through each batch.
for (int i = 0; i < batches; i++)
{
printf("\n\nBatch number -> %d\n", i);
end = start + batch_size;
if (remainder > 0)
{
remainder --;
end ++;
}
// Fill the parameters
param[i].array = array;
param[i].end = end;
param[i].start = start;
param[i].batch = i;
// Call the thread.
pthread_create(threads + index, NULL, method, (void *)&param[i]);
index++;
start = end;
}
for (int i = 0; i < batches; i++)
{
pthread_join(threads[i], NULL);
}
free(param);
free(threads);
free(array);
return 0;
}
Been playing with the index of the for loop(line 57) as i'm certain it's the cause of the issue. been getting some results but the main problem still persisted.
Code Works as intended. I'm a dumbas who didn't put the printf in the void function. like so:
void *method(void *p) {
Parameter *param = (Parameter *)p;
printf("\n\nBatch number -> %d\n", param->batch); //<-- moved from main method
for (int i = param->start; i < param->end; i++)
{
printf("Start:%d\tEnd:%d\tIndex:%d\tValue:%d\n", param->start, param->end, i,param->array[i]);
} }
Thanks for pointing it out that the program works

pthread_join hangs accordingly to random global variable value

I have built this code utilizing pthreads. The goal is to build an array X[N][D] and assign random values to it. You could read the elements of this array as the coefficients of some points.
On the next step I am trying to calculate an array distances[N]which holds all the distances between the last element (Nth) and each other element. The distances calculation is executed using pthreads.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <math.h>
#define N 10
#define D 2 //works for any d
#define NUM_THREADS 8
//double *distances;
//int global_index = 0;
pthread_mutex_t lock;
double *X;
typedef struct
{
//int thread_id;
double *distances;
int *global_index ;
pthread_mutex_t lock;
double *X;
}parms;
void *threadDistance(void *arg)
{
parms *data = (parms *) arg;
double *distances = data->distances;
double *X = data->X;
int *global_idx = data -> global_index;
int idx,j;
//long id = (long)arg;
pthread_mutex_lock(&lock);
while(*global_idx<N)
{
//printf("Thread #%ld , is calculating\n", id);
idx = *(global_idx);
(*global_idx)++;
pthread_mutex_unlock(&lock);
for(j=0 ; j<D; j++)
{
distances[idx] = pow(X[(j+1)*N-1]-X[j*N+idx], 2);
//printf("dis[%d]= ", dis);
//printf("%f\n",distances[idx]);
}
//printf("global : %d\n", *global_idx);
}
pthread_exit(NULL);
}
void calcDistance(double * X, int n, int d)
{
int i;
int temp=0;
pthread_t threads[NUM_THREADS];
double *distances = malloc(n * sizeof(double));
parms arg;
arg.X = X;
arg.distances = distances;
arg.global_index = &temp;
for (i=0 ; i<NUM_THREADS ; i++)
{
pthread_create(&threads[i], NULL, threadDistance, (void *) &arg);
}
for(i = 0 ; i<NUM_THREADS; i++)
{
pthread_join(threads[i], NULL);
}
/*----print dstances[] array-------*/
printf("--------\n");
for(int i = 0; i<N; i++)
{
printf("%f\n", distances[i]);
}
/*------------*/
free(distances);
}
int main()
{
srand(time(NULL));
//allocate the proper space for X
X = malloc(D*N*(sizeof(double)));
//fill X with numbers in space (0,1)
for(int i = 0 ; i<N ; i++)
{
for(int j=0; j<D; j++)
{
X[i+j*N] = (double) (rand() / (RAND_MAX + 2.0));
}
}
calcDistance(X, N, D);
return 0;
}
The problem is that the code executes completely only when N=100000. If N!=100000 the code just hangs and I have found that the source of the problem is the pthread_join() function. First of all I cannot understand why the hang depends on the value of N.
Secondly, I have tried printf()ing the value of global_index (as you can see it is commented out in this particular sample of code). As soon as I uncomment the printf("global : %d\n", *global_idx); command the program stops hanging, regardless of the value of N.
It seems crazy to me as the differences between hanging and not hanging are so irrelevant.
regarding:
pthread_mutex_lock(&lock);
while(*global_idx<N)
{
// ...
pthread_mutex_unlock(&lock);
The result is that after the first iteration of the loop, the mutex is always unlocked. Suggest moving the call to pthread_mutex_lock() to inside the top of the loop.
after making the above corrections, I then set N to 10000. Then re-compiled, etc. The result was a seg fault event, so the mis-handling of the mutex is not the only problem.
regarding:
* First of all I cannot understand why the hang depends on the value of N.*
it seems the program is actually crashing with a seg fault event, not hanging

Inner product space of arrays with posix threads

I want to read as input a table A and B from a user , and make an inner product space from them (a1b1+a2b2+……+anbn) and save it in a local_sum and then share it to an total_sum variable. I am doing the bellow code , but there is a segment fault. For some reason table A & B can't pass to function MUL. Any help would be great, thank you!
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#define N 2
int p;
int A[N],B[N];
int local_sum;
void *mul(void *arg)
{
int lines, start, end, i, j;
int id = *(int*)arg;
lines = N / p;
start = id * lines;
end = start + lines;
for (i = start; i < end; i++)
local_sum = A[i] * B[i] + local_sum;
return NULL;
}
int main (int argc, char *argv[])
{
int i;
pthread_t *tid;
if (argc != 2)
{
printf("Provide number of threads.\n");
exit(1);
}
p = atoi(argv[1]);
tid = (pthread_t *)malloc(p * sizeof(pthread_t));
if (tid == NULL)
{
printf("Could not allocate memory.\n");
exit(1);
}
printf("Give Table A\n");
for (int i = 0; i < N; i++)
{
scanf("%d", &A[i]);
}
printf("Give Table B\n");
for (int i = 0; i < N; i++)
{
scanf("%d", &B[i]);
}
for (i = 0; i < p; i++)
{
int *a;
a = malloc(sizeof(int));
*a = 0;
pthread_create(&tid[i], NULL, mul, a);
}
for (i = 0; i < p; i++)
pthread_join(tid[i], NULL);
printf("%d", local_sum);
return 0;
}
Let's see:
You want to have p threads, working on the vectors A and B.
You must be aware of that threads share the same memory, and might be interrupted at any time.
You've got p threads, all trying to write to one shared variable local_sum. This leads to unpredictable results since one thread overwrites the value another thread has written there before.
You can bypass this problem by ensuring exclusive access of one single thread to this variable by using a mutex or the like, or you could have one variable per thread, have each thread produce an intermediate result and after joining all threads, collapse all your intermediate results into the final one.
To do this, your main should look something like (assuming your compiler supports a recent C standard):
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#define N 2
/* these are variables shared amongst all threads */
int p;
int A[N], B[N];
/* array with one slot per thread to receive the partial result of each thread */
int* partial_sum;
/* prototype of thread function, just to be independent of the place mul will be placed in the source file... */
void *mul(void *arg);
int main (int argc, char** argv)
{
pthread_t* tid;
p = atoi(argv[1]);
const size_t n_by_p = N/p;
if(n_by_p * p != N)
{
fprintf(stderr, "Number of threads must be an integral factor of N\n");
exit(EXIT_FAILURE) ;
}
tid = calloc(p, sizeof(pthread_t));
partial_sum = calloc(p, sizeof(int)) ;
printf("Give Table A\n");
for(size_t i = 0; i < N; ++i)
{
scanf("%d",&A[i]);
}
printf("Give Table B\n");
for(size_t i = 0; i < N; ++i)
{
scanf("%d",&B[i]);
}
for (size_t i =0; i < p; ++i)
{
/* clumsy way to pass a thread it's slot number, but works as a starter... */
int *a;
a = malloc(sizeof(int));
*a = i;
pthread_create(&tid[i], 0, mul, a);
}
for (size_t i = 0; i < p; ++i)
{
pthread_join(tid[i], 0);
}
free(tid);
tid = 0;
int total_sum = 0;
for (size_t i = 0; i < p; ++i)
{
total_sum += partial_sum[i] ;
}
free(partial_sum);
partial_sum = 0;
printf("%d",total_sum);
return EXIT_SUCCESS;
}
Your threaded method mul should now write to its particular partial_sum slot only :
void *mul(void *arg)
{
int slot_num = *(int*)arg;
free(arg);
arg = 0;
const size_t lines = N/p;
const size_t start = slot_num * lines;
const size_t end = start + lines;
partial_sum[slot_num] = 0;
for(size_t i = start; i < end; ++i)
{
partial_sum[slot_num] += A[i]*B[i];
}
return 0;
}
Beware: This code runs smoothly, only if N is some integral multiple of p.
If this condition is not met, due to truncation in N/p, not all elements of the vectors will be processed.
However, fixing these cases is not the core of this question IMHO.
I spared all kinds of error-checking, which you should add, should this code become part of some operational setup...
if (tid=NULL)
-->
if (tid==NULL)
and
for (i=start;i<end;i++)
I suppose we need
for (i=0;i<end-start;i++)

Calling a void* function from main in C

Currently I am working on a program that uses threads to calculate the sum of square roots. My program works, however one of the requirements is to use the main thread to find the initial value, and as soon as I call the function Void *calc from main, the program breaks. Is there a certain way to make such a function call? Is this because the function is a pointer? Any help is appreciated.
#include <pthread.h>
#include <stdio.h>
#include <math.h>
#include <unistd.h>
#define NUM_THREADS 3
int ARGV;
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
double total = 0;
void *calc(void* t){
int ph = (int)t + 1;
int start, stop, interval_size;
interval_size = ARGV/(NUM_THREADS + 1);
start = ((ph) * interval_size) + 1;
stop = (ph * interval_size) + 1;
double ttl;
int i;
for (i = start; i <= stop; i++){
ttl = ttl + sqrt(i);
printf("Total Thread %i %lf\n", ph, ttl);
}
pthread_mutex_lock(&m);
total = total + ttl;
pthread_mutex_unlock(&m);
pthread_exit(NULL);
}
int main(int argc, char* argv[]) {
int i;
double ttl;
ARGV = atoi(argv[1]);
pthread_t ti[NUM_THREADS];
calc(0);
for (i = 0; i < NUM_THREADS; i++) {
pthread_create(&ti[i], NULL, calc,(void *)i);
}
/*for (i = 1; i <= (ARGV / 4) ; i++){
ttl = ttl + sqrt(i);
}*/
for (i = 0; i < NUM_THREADS; i++) {
pthread_join(ti[i], NULL);
}
total = total + ttl;
printf("Result: %lf\n", total);
}
The program breaks as in the function seems to only be called once, instead of each thread using the function. The only value printed out is some vague incorrect number.
Your calc function does pthread_exit. Now pthread_exit can and should be called from the main thread, so that's fine
To allow other threads to continue execution, the main thread
should terminate by calling pthread_exit() rather than exit(3).
But since this happens before any other thread has been created, the program just exits straight away, without ever starting other threads.

Reading array from threads, c, cygwin

I'm pretty new to threads and would like some insight. I'm trying to get the percentage each thread has completed for its calculation. Each thread will report its percentage to a different element of the same array. I have this working with pthread_join immediately after pthread_create and a separate thread for reading all the values of the array and printing the percentage but when I have all threads running after each other without waiting for the previous one to finish I get some weird behavior. This is how I'm accessing the shared (global) array.
//global
int *currentProgress;
//main
currentProgress = malloc(sizeof(int)*threads);
for(i=0; i<threads; i++)
currentProgress[i] = 0;
//child threads
currentProgress[myId] = (int)percent; //myId is unique
//progress thread
for(i=0; i<threads; i++)
progressTotal += currentProgress[i];
progressTotal /= threads;
printf("Percent: %d", progressTotal);
This is essentially the code I think is not being used correctly for multi-threads. When I print out the state of the shared array, I notice that as soon as another thread starts accessing the array (different element though), the previous element immediately goes to some random number... -2147483648 and when the latter element finishes the prior element continues like normal. Should I be using semaphores for this? I thought I could access different elements of an array at the same time and I thought reading them wasn't an issue.
This is the entire code:
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <stdint.h>
#include <pthread.h>
#include <string.h>
#define STDIN 0
int counter = 0;
uint64_t *factors;
void *getFactors(void *arg);
void *deleteThreads(void *arg);
void *displayProgressThread(void *arg);
int *currentProgress;
struct data
{
uint64_t num;
uint64_t incrS;
uint64_t incrF;
int threads;
int member;
} *args;
int main(int argc, char *argv[])
{
if(argc < 3) {printf("not enough arguments"); exit(1);}
int i;
int threads = atoi(argv[2]);
pthread_t thread_id[threads];
pthread_t dThread;
currentProgress = malloc(sizeof(int)*threads);
for(i=0; i<threads; i++)
currentProgress[i] = 0;
args = (struct data*)malloc(sizeof(struct data));
args->num = atoll(argv[1]);
args->threads = threads;
uint64_t increment = (uint64_t)sqrt((uint64_t)args->num)/threads;
factors = (uint64_t*)malloc(sizeof(uint64_t)*increment*threads);
pthread_create(&dThread, NULL, displayProgressThread, (void*)args);
//for the id of each thread
args->member = 0;
for(i=0; i<threads; i++)
{
args->incrS = (i)*increment +1;
args->incrF = (i+1)*increment +1;
pthread_create(&thread_id[i], NULL, getFactors, (void*)args);
usleep(5);
}
for(i=0; i<threads; i++)
{
pthread_join(thread_id[i], NULL);
}
sleep(1);
printf("done\n");
for (i=0; i<counter; i++)
printf("\n%llu : %llu", factors[++i], factors[i]);
return 0;
}
void *getFactors(void *arg)
{
uint64_t count;
int myId;
int tempCounter = 0, i;
struct data *temp = (struct data *) arg;
uint64_t number = temp->num;
float total = temp->incrF - temp->incrS, percent;
myId = temp->member++;
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
for(count=temp->incrS; count<=temp->incrF; count++)
{
percent = (float)(count-temp->incrS)/total*100;
currentProgress[myId] = (int)percent;
if (number%count == 0)
{
factors[counter++] = count;
factors[counter++] = number/count;
}
usleep(1);
}
usleep(1);
pthread_exit(NULL);
}
void *displayProgressThread(void *arg)
{
struct data *temp = (struct data *) arg;
int toDelete = 0;
while(1)
{
int i;
int progressTotal = 0;
char *percent = malloc(sizeof(char)*20);
for(i=0; i<toDelete; i++)
printf("\b \b");
for(i=0; i<temp->threads; i++){
progressTotal += currentProgress[i];
}
progressTotal /= temp->threads;
printf("|");
for(i=0; i<50; i++)
if(i<progressTotal/2)
printf("#");
else
printf("_");
printf("| ");
sprintf(percent, "Percent: %d", progressTotal);
printf("%s", percent);
toDelete = 53 + strlen(percent);
usleep(1000);
fflush(stdout);
if(progressTotal >= 100)
pthread_exit(NULL);
}
}
There are some non synchronized pieces of code that are accessed by the threads which cause this problem.
One first place to be synchronized is:
myId = temp->member++;
But more importantly is that, the main thread is doing:
args->incrS = (i)*increment +1;
args->incrF = (i+1)*increment +1;
while at the same time in the threads:
for(count=temp->incrS; count<= temp->incrF; count++)
{
percent = (float)(count-temp->incrS)/total*100;
currentProgress[myId] = (int)percent;
if (number%count == 0)
{
factors[counter++] = count;
factors[counter++] = number/count;
}
usleep(1);
}
The unsynchronized accesses mentioned above affect the calculation of percent value which results in such abnormal happenings. You have to do synchronization in all these places in order to get the kind of behavior you would expect.

Resources