segmentation fault when using threads - c - c

This is the first time that i am using threads and I started with a simple program. The program takes n arguments and creates n-2 threads. The thing is I get a segmentation fault and I don't know why.
Here's the code:
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
void *
removeBytes (int i, char* argv[])
{
printf ("%d, %s\n", i, argv[i]);
return NULL;
}
int main (int argc, char *argv[])
{
pthread_t threads[argc - 3];
int err;
int i;
int *ptr[argc - 3];
printf ("argc = %d\n", argc);
for (i = 0; i < argc -3; i++)
{
err =
pthread_create (&(threads[i]), NULL,
removeBytes(i+1,&argv[i+1]), NULL);
if (err != 0)
{
printf ("\nCan't create thread: [%d]", i);
}
else
{
printf ("\nThread created successfully\n");
}
}
for (i = 0; i < argc - 3; i++)
{
pthread_join (threads[i], (void **) &(ptr[i]));
printf("pthread_join - thread %d",i);
}
return 0;
}
Example: my program is called mythread so when I run it ./mythread f1 f2 f3 f4 f5 f6 the output is:
argc = 6
1,f2
Thread created successfully
2,f4
Thread created successfully
3, (null)
And why does it take f2 as argv[1] and f4 as argv[2]?
UPDATE:
typedef struct{
int i;
char* argv;
}Data;
void* removeBytes(void* arg){
Data* data = (Data*)arg;
printf("%d, %s\n",data->i, data->argv);
free(data);
return NULL;
}
int main(int argc, char** argv){
Data* data;
pthread_t threads[argc-3];
int i;
int err;
for(i=0; i < argc-3;i++){
data = (Data*)malloc(sizeof(Data));
data->i=i+1;
data->argv=argv[i+1];
err = pthread_create(&(threads[i]),NULL,removeBytes,data);
if(err != 0){
printf("\nCan't create thread %d",i);
}
else{
printf("Thread created successfully\n");
}
}
return 0;
}
for ./mythread f1 f2 f3 f4 f5 f6 f7 f8 the output is:
5 x "Thread created successfully". It doesn't print i or argvi[i].

There is problem in
pthread_create (&(threads[i]), NULL,
removeBytes(i+1,&argv[i+1]), NULL);
Syntax of pthread_create is
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
It takes start routine as a callback. In your case, you are calling removeBytes in main thread that is before spawning and returning NULL. So, callback is NULL.
So, modify your removeBytes accordingly as per your need and call
pthread_create (&(threads[i]), NULL,
removeBytes, argv[i+1]);

You're not using pthread_create correctly :
pthread_create (&(threads[i]), NULL,
removeBytes(i+1,&argv[i+1]), NULL);
Here you're just calling removeBytes() and passing the result (NULL) as an argument of pthread_create().
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
The third argument should be a pointer to a void* myThread(void*) function. If you want to pass arguments to your thread, you should use the void* parameter and pass it as the third argument of pthread_create.
You could take a look at this in order to learn how to use the pthread library.
Also, you probably want to to something like this :
typedef struct {
int i;
char* argv;
} Data;
void * removeBytes (void* arg)
{
Data* data = (Data*) arg;
printf ("%d, %s\n", data->i, data->argv);
free(data);
return NULL;
}
And then create the thread like this:
Data* data = (Data*)malloc(sizeof(Data));
data->i = i;
data->argv = argv[i+1];
err = pthread_create (&(threads[i]), NULL, removeBytes, data);

It takes f2 as argv[1] and f4 as argv[2] simply because when you pass &argv[i+1] you actually pass pointer to the (i+1)-th element of the array and you also pass i+1 as index.
So if you have argv equals [mythread, f1, f2, f3, f4, f5, f6] at first you'll get [f1, f2, f3, f4, f5, f6] in removeBytes. And when you're accessing i+1 = 1 element you'll get f2. Next time you'll get [f2, f3, f4, f5, f6] and i+1 = 2 so you'll get f4

With
pthread_create (&(threads[i]), NULL,
removeBytes(i+1,&argv[i+1]), NULL);
You are calling removeBytes() instead of passing it as parameter.
Also, You can pass only one argument to thread function. So you need to put multiple arguments in a structure. Something like:
struct thread_args {
int i;
char *argv;
}
#your main code
struct thread_args *thargs;
for (i = 0; i < argc -3; i++)
{
thargs = malloc(sizeof(*thargs));
thargs->i = i+1;
thargs->argv = argv[i+1];
err =
pthread_create (&(threads[i]), NULL,
removeBytes, thargs);
if (err != 0)
{
printf ("\nCan't create thread: [%d]", i);
}
else
{
printf ("\nThread created successfully\n");
}
}
#make sure to free up thargs as well.
And update thread function as
void *removeBytes (void *arg)
{
int i;
char *argv;
struct thread_args *thargs = (struct thread_args *) arg;
i = thargs->i;
argv = thargs->argv;
printf ("%d, %s\n", i, argv);
return NULL;
}

Related

Passing an int to a pthread

Can't get the pthread's last parameter to pass through as an actual int. I would like to be able to access the 1 that is put in the last parameter of pthread_create. Any help would be greatly appreciated!
#include <pthread.h>
#include <unistd.h>
#include <malloc.h>
#define MAX 5
int arr[MAX];
int p0 = 0;
int p1 = 0;
int p2 = 0;
int p3 = 0;
int p4 = 0;
void *process(void *arg);
int main(int argc, char *argv[]) {
if(argc != 7) {
printf("must be 6 ints");
return -1;
}
int quantum = atoi(argv[1]);
p0 = atoi(argv[2]);
p1 = atoi(argv[3]);
p2 = atoi(argv[4]);
p3 = atoi(argv[5]);
p4 = atoi(argv[6]);
This below is the pthread I am referring to.
int *pointer0 = malloc(sizeof(*pointer0));
*pointer0 = p0;
/* intialize thread 1 */
pthread_t tid0;
pthread_attr_t attr0;
pthread_attr_init(&attr0);
pthread_create(&tid0, &attr0, process, 1);
pthread_join(tid0, NULL);
//if the time remaining of process is not zero, run process[i] again
return 0;
}
void *process(void *arg) {
//char **pointer = (char**) arg;
//int burst = **pointer;
int burst = 0;
//int i = atoi(arg);
printf("%ls", (int *)arg);
pthread_exit(NULL);
}
If you read the manual pages of pthread_create() function, you will notice that you are passing an int instead of a void* in the last argument.
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
To solve this problem, create a variable to store the int value and pass it through the pthread_create() function using its address. Then, in the process() function, cast the argument to an int.
int main () {
// (...)
int arg = 1;
pthread_create(&tid0, &attr0, process, &arg);
// (...)
return 0;
}
void *process (void *arg) {
int arg = *((int *) arg);
// (...)
return NULL;
}
Now, notice that the variable arg I just declared in the main() function will be always available, once the program only exits the main() function at the end. If the pthread_create() function is called inside another function, it is highly recommended that you allocate the memory dynamically to ensure it is always available even if the function is exited. Do not forget to free the memory before exiting the process() function.
int foo () {
// (...)
int *arg = malloc( sizeof(int) );
if ( !arg ) {
fprintf(stderr, "error: allocating memory");
return 0;
}
*arg = 1;
pthread_create(&tid0, &attr0, process, arg);
// (...)
return 0;
}
void *process (void *arg) {
int value = *((int *) arg);
// (...)
free(arg);
return NULL;
}
If you want to pass more variables trough the pthread_create() function, declare a struct and repeat the same process.
typedef struct {
char name[50];
char surname[50];
int age;
} person_t;
int foo () {
// (...)
person_t *arg = malloc( sizeof(person_t) );
if ( !arg ) {
fprintf(stderr, "error: allocating memory");
return 0;
}
sprintf( arg->name , "Miguel" );
sprintf( arg->name , "Carvalho" );
arg->age = 22;
pthread_create(&tid0, &attr0, process, arg);
// (...)
return 0;
}
void *process (void *arg) {
person_t person = *((person_t *) arg);
printf( "%s; %s; %d\n", person.name, person.surname, person.age);
// (...)
free(arg);
return NULL;
}

How to pass an array properly to a threaded function with a structure

Ive been beating my head against the wall for days about this because I cant seem to find a good solution to this issue. I need to pass two arrays into a threaded function using a structure. One array is the structure Im needing to sum and the other is where the result of that summation needs to be stored and then I need to sum them one final time in the main program to get the total value.
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#define NUMBER_OF_THREADS 2
typedef struct
{
double s[NUMBER_OF_THREADS];
double a[];
int tid;
} parmListType;
void *sum_arr(void *parms)
{
pthread_exit(NULL);
}
int main(int argc, char **argv)
{
pthread_t threads[NUMBER_OF_THREADS];
int status, i;
double arr[1000000]={};
double sum[NUMBER_OF_THREADS];
printf("debug_size_arr: %ld\n",sizeof(arr)/sizeof(double));
for(int i=0;i<sizeof(arr)/sizeof(double);i++)
{
arr[i]=i;
}
parmListType *parms;
for(i=0; i<NUMBER_OF_THREADS; i++)
{
printf("debug: Main here. Creating thread %d\n", i);
// dynamically create a structure to hold the parameter list
parms = (parmListType *)malloc( sizeof(parmListType));
//printf("debug_sizeof_paramA: %ld\n",sizeof(parms->a));
//parms->s[NUMBER_OF_THREADS/sizeof(double)]= *sum;
parms->tid = i;
status = pthread_create(&threads[i], NULL, sum_arr, (void *) parms);
if(status != 0)
{
printf("oops. pthread_create returned error code %d\n", status);
exit(-1);
}
printf("first for\n");
}
for(i=0; i<NUMBER_OF_THREADS; i++)
{
status=pthread_join(threads[i], NULL);
}
exit(0);
}
//// there are loads of errors in this code, I need guidance about how Im
////supposed to set this up right.
You can do st similar to the below:
struct ThreadArgs
{
int type;
//others
};
void* Thread(void* thread_args)
{
int type;
pthread_detach(pthread_self());
type = ((struct ThreadArgs *) thread_args)->type;
return NULL;
}
int main()
{
pthread_t thread_id;
struct ThreadArgs* thread_args;
thread_args = (struct ThreadArgs *) malloc(sizeof(struct ThreadArgs));
if (thread_args == NULL)
PanicWithError("malloc() failed");
thread_args->type = 1;
if (pthread_create(&thread_id, NULL, Thread, (void *) thread_args) != 0)
PanicWithError("pthread_create() failed");
while (1)
{}
return 0;
}

pthread_create and passing an integer as the last argument

I have the following functions :
void *foo(void *i) {
int a = (int) i;
}
int main() {
pthread_t thread;
int i;
pthread_create(&thread, 0, foo, (void *) i);
}
At compilation, there are some errors about casting ((void *) i and int a = (int) i). How can I pass an integer as the last argument of pthread_create properly?
Building on szx's answer (so give him the credit), here's how it would work in your for loop:
void *foo(void *i) {
int a = *((int *) i);
free(i);
}
int main() {
pthread_t thread;
for ( int i = 0; i < 10; ++1 ) {
int *arg = malloc(sizeof(*arg));
if ( arg == NULL ) {
fprintf(stderr, "Couldn't allocate memory for thread arg.\n");
exit(EXIT_FAILURE);
}
*arg = i;
pthread_create(&thread, 0, foo, arg);
}
/* Wait for threads, etc */
return 0;
}
On each iteration of the loop, you're allocating new memory, each with a different address, so the thing that gets passed to pthread_create() on each iteration is different, so none of your threads ends up trying to access the same memory and you don't get any thread safety issues in the way that you would if you just passed the address of i. In this case, you could also set up an array and pass the addresses of the elements.
You can allocate an int on the heap and pass it to pthread_create(). You can then deallocate it in your thread function:
void *foo(void *i) {
int a = *((int *) i);
free(i);
}
int main() {
pthread_t thread;
int *i = malloc(sizeof(*i));
pthread_create(&thread, 0, foo, (void *) i);
}
You should cast the address of i (rather than the value of i as you do now) in the last argument of pthread_create().
pthread_create(&thread, 0, foo, (void *) &i);
^ is missing
And the casting is wrong in your function too. It should be:
int a = *((int*) i);
If you intend to read the value, you should also initialize i to some value in main() as it's uninitialized now.
2 Use proper definition for main():
int main(void)
or int main(int argc, char *argv[]) or its equivalent.
Old question, but I faced the same problem today, and I decided not to follow this path.
My application was really about performance, so I chose to have this array of ints declared statically.
Since I don't know a lot of applications where your pthread_join / pthread_cancel is in another scope than your pthread_create, I chose this way :
#define NB_THREADS 4
void *job(void *_i) {
unsigned int i = *((unsigned int *) _i);
}
int main () {
unsigned int ints[NB_THREADS];
pthread_t threads[NB_THREADS];
for (unsigned int i = 0; i < NB_THREADS; ++i) {
ints[i] = i;
pthread_create(&threads[i], NULL, job, &ints[i]);
}
}
I find it more elegant, more efficient, and you don't have to worry about freeing since it only lives in this scope.
While this is an old question there is one option missing when all you need is to pass a positive integer like a descriptor: you can pass it directly as the address, while it it a hack it works well and avoid allocating anything :)
NOTE: the size of the integer must match the size of a pointer on your OS but nowadays most systems are native 64bits.
#include <pthread.h>
#include <inttypes.h>
#include <stdio.h>
void *_thread_loop(void *p)
{
uint64_t n = (uint64_t)p;
printf("received %llu\n", n);
return NULL;
}
int main(int argc, char const *argv[])
{
pthread_t read_thread_id;
uint64_t n = 42;
pthread_create(&read_thread_id, NULL, _thread_loop, (void *)n);
pthread_join(read_thread_id, NULL);
return 0;
}

create thread - passing arguments

I am attempting on creating multiple threads that each thread calculates a prime. I am trying to pass a second argument to a function using thread create. It keeps throwing up errors.
void* compute_prime (void* arg, void* arg2)
{
here is my main() with the create thread. &primeArray[i] after &max_prime is giving me the errors.
for(i=0; i< num_threads; i++)
{
primeArray[i]=0;
printf("creating threads: \n");
pthread_create(&primes[i],NULL, compute_prime, &max_prime, &primeArray[i]);
thread_number = i;
//pthread_create(&primes[i],NULL, compPrime, &max_prime);
}
/* join threads */
for(i=0; i< num_threads; i++)
{
pthread_join(primes[i], NULL);
//pthread_join(primes[i], (void*) &prime);
//pthread_join(primes[i],NULL);
//printf("\nThread %d produced: %d primes\n",i, prime);
printf("\nThread %d produced: %d primes\n",i, primeArray[i]);
sleep(1);
}
the error i get is:
myprime.c: In function âmainâ:
myprime.c:123: warning: passing argument 3 of âpthread_createâ from incompatible pointer type
/usr/include/pthread.h:227: note: expected âvoid * (*)(void *)â but argument is of type âvoid * (*)(void *, void *)â
myprime.c:123: error: too many arguments to function âpthread_createâ
It works fine if i take out the second argument.
You can only pass a single argument to the function that you are calling in the new thread. Create a struct to hold both of the values and send the address of the struct.
#include <pthread.h>
#include <stdlib.h>
typedef struct {
//Or whatever information that you need
int *max_prime;
int *ith_prime;
} compute_prime_struct;
void *compute_prime (void *args) {
compute_prime_struct *actual_args = args;
//...
free(actual_args);
return 0;
}
#define num_threads 10
int main() {
int max_prime = 0;
int primeArray[num_threads];
pthread_t primes[num_threads];
for (int i = 0; i < num_threads; ++i) {
compute_prime_struct *args = malloc(sizeof *args);
args->max_prime = &max_prime;
args->ith_prime = &primeArray[i];
if(pthread_create(&primes[i], NULL, compute_prime, args)) {
free(args);
//goto error_handler;
}
}
return 0;
}
In case of std::thread, the user can pass arguments to the thread function in the following method
std::thread(funcName,arg1,arg2);
for instance,
//for a thread function,
void threadFunction(int x,int y){
std::cout << x << y << std::endl;
}
// u can pass x and y values as below
std::thread mTimerThread;
mTimerThread = std::thread(threadFunction,1,12);
This is the code of Manakarse , everything is really good but you need a
pthread_join(thread[i],NULL)
just to be sure all of threads will successfully execute before end of main thread("main will "waiting" while all of threads aren't finished yet)
;
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct
{
int stop_flag;
char name[30];
} _process_data;
typedef struct
{
int meter_no;
int port_no;
} _process_control;
typedef struct
{
_process_data *process_data;
_process_control *process_control;
} compute_prime_struct;
void *compute_prime (void *args)
{
compute_prime_struct *actual_args = args;
printf("actual_args->process_data->stop_flag [%d]\n",actual_args->process_data->stop_flag);
printf("actual_args->process_data->name [%s]\n",actual_args->process_data->name);
printf("actual_args->process_control->meter_no [%d]\n",actual_args->process_control->meter_no);
printf("actual_args->process_control->port_no [%d]\n",actual_args->process_control->port_no);
free(actual_args);
return 0;
}
void fill_data(_process_data *process_data,_process_control *process_control)
{
process_data->stop_flag=1;
process_data->name[0]='P';
process_control->meter_no=6;
process_control->port_no=22;
pthread_t tid;
compute_prime_struct *args = malloc(sizeof (*args));
args->process_data = malloc(sizeof (*args->process_data));
args->process_control = malloc(sizeof (*args->process_control));
memcpy (args->process_data, process_data, sizeof (args->process_data));
memcpy (args->process_control, process_control, sizeof (*args->process_control));
if(pthread_create(&tid, NULL, compute_prime, args))
{
free(args);
printf("Error here");
}
sleep(1);
}
int main()
{
_process_data process_data;
_process_control process_control;
fill_data(&process_data,&process_control);
return 0;
}

How to cast an integer to void pointer?

While working with Threads in C, I'm facing the warning
"warning: cast to pointer from integer of different size"
The code is as follows
#include<stdio.h>
#include<sys/types.h>
#include<stdlib.h>
#include<pthread.h>
void *print(void *id)
{
int a=10;
printf("My thread id is %ld\n",pthread_self());
printf("Thread %d is executing\n",id);
return (void *) 42;
}
int main()
{
pthread_t th[5];
int t;
int i;
int status;
void *ret;
for(i=0;i<5;i++)
{
status=pthread_create(&th[i],NULL,print,(void *)i); //Getting warning at this line
if(status)
{
printf("Error creating threads\n");
exit(0);
}
pthread_join(th[i],&ret);
printf("--->%d\n",(int *)ret);
}
pthread_exit(NULL);
}
Can anybody explain how to pass an integer to a function which receives (void * ) as a parameter?
This is a fine way to pass integers to new pthreads, if that is what you need. You just need to suppress the warning, and this will do it:
#include <stdint.h>
void *threadfunc(void *param)
{
int id = (intptr_t) param;
...
}
int i, r;
r = pthread_create(&thread, NULL, threadfunc, (void *) (intptr_t) i);
Discussion
This may offend your sensibilities, but it's very short and has no race conditions (as you'd have if you used &i). No sense in writing a few dozen lines of extra code just to get a bunch of numbered threads.
Data races
Here is a bad version with a data race:
#include <pthread.h>
#include <stdio.h>
#define N 10
void *thread_func(void *arg)
{
int *ptr = arg;
// Has *ptr changed by the time we get here? Maybe!
printf("Arg = %d\n", *ptr);
return NULL;
}
int main()
{
int i;
pthread_t threads[N];
for (i = 0; i < N; i++) {
// NO NO NO NO this is bad!
pthread_create(&threads[i], NULL, thread_func, &i);
}
for (i = 0; i < N; i++) {
pthread_join(threads[i], NULL);
}
return 0;
}
Now, what happens when I run it with the thread sanitizer?
(Also, check out how it prints "5" twice...)
==================
WARNING: ThreadSanitizer: data race (pid=20494)
Read of size 4 at 0x7ffc95a834ec by thread T1:
#0 thread_func /home/depp/test.c:9 (a.out+0x000000000a8c)
#1 <null> <null> (libtsan.so.0+0x000000023519)
Previous write of size 4 at 0x7ffc95a834ec by main thread:
#0 main /home/depp/test.c:17 (a.out+0x000000000b3a)
Location is stack of main thread.
Thread T1 (tid=20496, running) created by main thread at:
#0 pthread_create <null> (libtsan.so.0+0x0000000273d4)
#1 main /home/depp/test.c:18 (a.out+0x000000000b1c)
SUMMARY: ThreadSanitizer: data race /home/depp/test.c:9 thread_func
==================
Arg = 1
Arg = 2
Arg = 3
Arg = 4
Arg = 5
Arg = 6
Arg = 7
Arg = 8
Arg = 9
Arg = 5
ThreadSanitizer: reported 1 warnings
you can do something like this:
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <pthread.h>
struct th {
pthread_t thread;
int id;
int ret;
};
void *print(void *id) {
int a=10;
struct th *self = (struct th *) id;
printf("My thread id is %ld\n",pthread_self());
printf("Thread %d is executing\n",self->id);
self->ret = random();
return;
}
int main(void) {
struct th th[5];
int t;
int i;
int status;
void *ret;
for(i=0;i<5;i++) {
th[i].id = i;
status=pthread_create(&th[i].thread,NULL,print,&th[i]); //Getting warning at this line
if(status) {
printf("Error creating threads\n");
exit(0);
}
}
for (i=0;i<5;i++) {
pthread_join(th[i].thread,&ret);
printf("%d--->%d\n",th[i].id,th[i].ret);
}
pthread_exit(NULL);
}
will output:
My thread id is 4496162816
My thread id is 4497870848
My thread id is 4498944000
My thread id is 4498407424
Thread 0 is executing
Thread 1 is executing
My thread id is 4499480576
Thread 3 is executing
Thread 2 is executing
0--->1804289383
Thread 4 is executing
1--->846930886
2--->1714636915
3--->1681692777
4--->1957747793
passing a unique pointer to each thread wont race, and you can get/save any kind of information in the th struct
you can pass the int value as void pointer like (void *)&n where n is integer, and in the function accept void pointer as parameter like void foo(void *n);and finally inside the function convert void pointer to int like, int num = *(int *)n;. this way you won't get any warning.
change:
status=pthread_create(&th[i],NULL,print,(void *)i);
to:
status=pthread_create(&th[i],NULL,print,(reinterpret_cast<void*>(i));
The reinterpret_cast makes the int the size of a pointer and the warning will stop. Basically its a better version of (void *)i.

Resources