segmentation fault when converting (void*) to (int*) - c

I Wrote a multithreaded Pthread program that outputs prime numbers. This program works as follows: The user will run the program and will enter a number on the command line. The program will then create a separate thread that outputs all the prime numbers less than or equal to the number that the user entered.
The codes:
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<math.h>
#include<string.h>
#define true 1
#define false 0
void* print_prime(void* arg)
{
int temp;
temp = *((int*)arg);//If I change it to 'temp = (int)arg',it runs well
int flag;
int i,j;
for(i = 2 ; i <= temp ; i++)
{
flag = true;
for(j = 2 ; j <= (int)sqrt(i) ; j++)
{
if(i%j == 0)
{flag = false;break;}
}
if(flag == true)
printf("%d\n",i);
}
}
int main(int argc,char *argv[])
{
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
if(argc != 2)
{perror("Parameters not enough");exit(0);}
int arg = atoi(argv[1]);
if(pthread_create(&tid,&attr,print_prime,(void*)arg))
{perror("Pthread created not successfully");exit(0);}
pthread_join(tid,NULL);
return 0;
}
when I wrote in the terminal as:./pthread_test 10,a segmentation fault(core dump) occurs.I use dmesg and addr2line -e pthread_test 0xxxxxx to locate the error.It turns to the instruction temp = *((int*)arg).
In pthread_create(&tid,&attr,print_prime,(void*)arg),I have converted arg to a void* type variable,why I was wrong for using *(int*)arg?

When you are passing the int as a pointer to void it does not alter the fact that you are sending the value of int and not its address. When you do *(int *) you are trying to obtain the content of the address(pointer to int) that you would obtain from the argument void. Obviously since you sent the value in int and not its address it will not work. Try maybe doing (void *)(&arg). But i think it is pointless castings. Why would you need to do *(int *)? Is there any particular reason? Do you understand the concept of pointer to void?

from the define of function
int pthread_create(pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine) (void *),
void *arg);
the type of fourth parameter is void*, but in your code, you write (void*)arg, so this is wrong.
you can change to:
pthread_create(&tid,&attr,print_prime,(void*)&arg)
The reason, arg in an int, and the value may be 100(just a example, your input value). If you use (void*)arg, that's means thay you want change 100(int type) to void* type. so your code fault, because your code read the memmory address 100. In should pass the address of value 100 to pthread_create, so you need write (void*)&arg.

Here you are passing the value
if(pthread_create(&tid,&attr,print_prime,(void*)arg))
Not the address. So you converted some value as void pointer and de-referencing it in another function. So this caused the problem.
if(pthread_create(&tid,&attr,print_prime,(void*)&arg)) is the correct one

Related

Passing an array to pthread_create

So i was trying to make a program that creates a thread in c whose job is to find the maximum of 2 given numbers. The first program that i wrote (named askisi.c) was the following:
#include <pthread.h>
#include <stdio.h>
#include <sys/types.h>
int max;
void *max_of_two(void *param);
int main(int argc , char *argv[])
{
pthread_t tid;
pthread_attr_t attr;
if (argc != 3)
{
fprintf(stderr,"You have to give 2 numbers... \n");
return -1;
}
pthread_attr_init(&attr);
pthread_create(&tid,&attr,max_of_two,argv);
pthread_join(tid,NULL);
printf("max = %d\n",max);
}
void *max_of_two(void *param)
{
if(atoi(*param[1]) >= atoi(*param[2]))
max = atoi(*param[1]);
else
max = atoi(*param[2]);
pthread_exit(0);
}
But using gcc in Linux i got these errors:
Now after a lot of research i found that my the function max_of_two should be written like this:
void *max_of_two(void *param)
{
char **arguments = (char**)param;
if(atoi(arguments[1]) >= atoi(arguments[2])){
max = atoi(arguments[1]);}
else
max = atoi(arguments[2]);
pthread_exit(0);
}
The first problem is that i didn't find any explanation on why my first program didn't work. The second one is that i didn't find an understandable explanation on what the instruction char **arguments = (char**)param; actually does.
void is not a real type, and in that context it means the function expect any type and its up to the programmer to decide which is done with casting.
So by doing char **arguments = (char**)param; you casted param into char ** and assigned that cast to the variable arguments.

Pass value by reference in pthread

#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
void* func(void*);
int main()
{
int numb = 0;
pthread_t pid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&pid, &attr, func, (void*)&numb);
printf("%s%d\n", "Number: ", numb);
return 0;
}
//..............defintation...............
void* func(void* data)
{
int* numb = (int*)data;
*numb = 1000;
}
I want to pass the number to the function "func" by reference. I did so by passing the address of the number "(void*)&numb". I changed the value to 1000 in the function and printed the value in main, but the output is 0 instead of 1000.
Thanks!!!
This is a classic race condition.
Your computer got to the printf in main before it got to the *numb = 1000 in func.
You will need a condition variable or some other form of concurrency primitive in order to synchronise access to this datum.
These are the very basics of multi-threaded programming, so you should read a book on the subject rather than guessing.

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;
}

Threads receiving the same ID in C

Here is a block of code that creates a number of threads provided by the user, each thread then generates a random number and calculates its squareroot. I cannot figure out why the threads are getting the same ID, line 64 is the culprit as it is where the threads are being created. I suspect that there is something happening in the loop that is causing the threads to all be generated at the same time.
////////////////////////////////////////////////
//
//
// Zach
//
//
//
//
////////////////////////////////////////////////
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <math.h>
void *squareroot(void *num1)
{
int *id = (int *)num1;
int incoming = rand()/100;
float *outgoing = (float *)malloc(sizeof(float));
printf("%d \n", *id);
printf("%d\n", incoming);
*outgoing = 5.000;
//Calculate the square root of the number passed to the function
*outgoing = sqrt(incoming);
return outgoing;
}
int main(int argc, char* argv[])//testing funcion
{
srand(time(NULL));
int i, j;
int *temp = (int *)malloc(sizeof(int));
if (argc != 2)
{
printf ("ERROR: Enter a number\n");
return 1;
}
int loop = atoi(argv[1]); //grabbing the integer supplied by user
pthread_t thread_id[loop];
void *exit_status;
float *thread_result;
for(i = 0; i < loop; i++)
{
pthread_create(&thread_id[i], NULL, squareroot, &i);
}
for(j = 0; j < loop; j++)
{
pthread_join(thread_id[j], &exit_status);
thread_result = (float *)exit_status;
printf("%f\n", *thread_result);
}
}
I think what is happening is that your loop finishes creating all the threads (or at least some of them) before any of the threads actually run and extract their unique id.
Because you're passing a pointer to i, when each thread finally gets around to checking its parameter, i is already finished... Or at least partway through. The danger is that multiple threads might see the same value for i. It's even worse that you never copy the value out of that pointer - you always dereference it. That means it might change in the middle of your thread's execution.
What you should do instead is pretend it is a pointer:
pthread_create(&thread_id[i], NULL, squareroot, (void*)i);
And in your thread function:
int id = (int)num1;
This works because the pointer is passed by value. Whatever value you provide is the value that goes into the thread function. Previously it didn't work because you passed a pointer to a value that could change in another thread.
PS: Don't forget to free the result from each thread in your loop at the end. At the moment you're not cleaning up memory that you allocated.

How to pass parameters to the function called by clone()?

I have to use the clone() system call in the main-function to get 2 threads. (I know, there are other options, but in this case, it has to be clone()).
The system call works and both threads arrive in the designated function (foo). But in this function I need them to call another function with this signature:
void increment(int* a, int b)
(Sidenote: It adds b * 1 to a. (= a+b))
The important thing is, that both, a and b, are declared in the main-function and I don't know how to pass them to foo.
I already tried different things, but without success. I've gotten a hint: Use an adapter.
But I have no clue how to do this. (I also dont know how to use the args in clone with int.)
Any suggestions?
One of the arguments to clone() is a void* arg. This lets you pass a void pointer to your function. In order to pass an int pointer and an int instead, you have to create a struct with an int pointer and int assigned to a and b respectively, then cast a pointer to that struct into a void pointer. Then inside the function you reverse the process.
My C is a little rusty and I haven't compiled this, so don't quote me on it, but it should look roughly like this:
struct clone_args {
int* a;
int b
};
int main(int argc, char* argv[])
{
struct clone_args args;
args.a = a;
args.b = b;
void* arg = (void*)&args;
clone(fn, ..., arg, ...);
}
int fn(void* arg)
{
struct clone_args *args = (struct clone_args*)arg;
int* a = args->a;
int b = args->b;
}
Note: take care that the struct you create is still in scope when fn is called, as it isn't copied. You might have to malloc it.
Here is the example code:
#define stacksize 1048576
typedef struct
{
int ii;
int jj;
} someinput1;
static int /* Start function for cloned child */
childFunc(someinput1 *struc)
{
printf("Child: PID=%ld PPID=%ld\n", (long) getpid(), (long) getppid());
printf("Hi!! I am child process created by Clone %ld \n",(long) getpid());
printf("Value of x %d %d\n",struc->ii,struc->jj);
}
int main()
{
someinput1 inputtest;
int i;
char *stack; /* Start of stack buffer */
char *stack1; /* End of stack buffer */
pid_t pid;
stack = malloc(stacksize);
stack1 = stack + stacksize;
for (i = 0;i<5;i++)
{
inputtest.ii = i+5;
inputtest.jj = inputtest.ii + 10;
pid = clone(childFunc, stack1, NULL, (void *) (&inputtest));
printf("clone returned -- %ld \n", (long) pid);
}
sleep(1);
exit(EXIT_SUCCESS);
}

Resources