Hi I am having trouble passing an integer argument to a thread and calculation the factorial using that integer. Here is my code.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <ctype.h>
void * factorial(void * number) {
int factorial = 1;
int counter = 1;
int newnum = *((int*)number);
printf("%d", newnum);
pthread_exit(NULL);
}
void * sumup( void * number) {
}
int main(int argc, char *argv[]) {
if(argc != 2) {
printf("Argument number error\n");
exit(1);
}
pthread_t thread1;
pthread_t thread2;
int i;
for(i = 0; i < argc; i++){
printf(argv[i]);
printf("\n");
}
int rc;
void * t = argv[1];
rc = pthread_create(&thread1, NULL, factorial, (void*)t );
if (rc != 0) {
printf("There was an error creating the thread\n");
exit(1);
}
pthread_exit(NULL);
exit(0);
}
Right now i am just trying to print the integer sent to get it working properly but here is my output:
./Task1
5
1162608693
It should printing out 5 instead of 1162608693
argv table stores pointers to characters. By doing:
void * t = argv[1];
int newnum = *((int*) t );
what you are trying to print is integer value of string "5". You are passing address of string:
'5' '\0'
casted to pointer to int, therefore you try to read integer value of first sizeof(int) bytes which yields:
5 0 [and you read sizeof(int)-2 bytes out of range]
which results in undefined behavior.
SOLUTION
To convert to integer a string passed as argument to your program use atoi or strtol which does better error checking.
Related
I just started programming in multiple threading and tinkering with some templates around, I produced this possibly horrible code:
#include <stdio.h>
#include <pthread.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
typedef struct __myarg_t //argument struct?
{
int a;
char *b;
} myarg_t;
typedef struct __myret_t //return thread struct?
{
int x;
char *y;
} myret_t;
char cat[100] = ""; //used for concatenation of argv
void *mythread(void *arg)
{
myarg_t *m = (myarg_t *)arg;
int print_index = 0;
printf("THREAD ID: %lu\n", pthread_self());
for (print_index = 0; print_index < m->a; print_index++)
{
printf("Printing %d th character %c\n", print_index, *(m->b + print_index));//spelling the words
}
myret_t *rfin = malloc(sizeof(myret_t));
rfin->x = 1;
strcat(cat, m->b);//concatenating argv with
strcat(cat, " "); //a space to cat
rfin->y = cat;//reassigning the new sentence to rfin
return (void *)rfin;
}
int main(int argc, char *argv[])
{
if (argc == 1)
{
printf("Enter a word as argument before commandline.\nExiting...\n");
exit(0);
}
int rc = 0;
pthread_t p[argc - 1]; //total threads
myret_t *m; //return thread
myarg_t args; //argument thread?
int i = 1;
while (i < argc) //creating threads:
{
printf("THREAD:\t%d\n", i);
args.a = strlen(argv[i]);
args.b = (char *)malloc(strlen(argv[i]));
strcpy(args.b, argv[i]);
pthread_create(&p[i - 1], NULL, mythread, &args);
i++;
}
i = 1;
while (i < argc) // Wait for threads to complete
{
pthread_join(p[i - 1], (void **)&m);
i++;
}
printf("returned %d %s\n", m->x, m->y); //end concatenation result for myret_t *m;
return 0;
}
so when I execute it:
gcc -g task2.c -o thread -Wall -pthread
./thread hello there
It gives me the following as the result:
THREAD: 1
THREAD: 2
THREAD ID: 139848453601024
Printing 0 th character t
Printing 1 th character h
Printing 2 th character e
Printing 3 th character r
Printing 4 th character e
THREAD ID: 139848445208320
Printing 0 th character t
Printing 1 th character h
Printing 2 th character e
Printing 3 th character r
Printing 4 th character e
returned 1 there there
Instead of hello there. Is there some problem with the way I am concatenating? Should I be using another thread to do it?
Should I lock the concatenation part of the code because different threads are using it at the same time?
Any idea as to where I am going wrong? Any help/advice/criticism is more than welcome.
You have a race condition in your code -- you pass a pointer to args to the first thread, and then the main() function immediately overwrites the member-variables in the object that the pointer points to, while the first thread is running in parallel, so the first thread (usually) doesn't get a chance to see the original args.a or args.b values before they got overwritten. To avoid this, you could allocate a separate args struct for each thread, instead:
myarg_t * args = (myarg_t *) malloc(sizeof(myarg_t));
args->a = strlen(argv[i]);
args->b = (char *)malloc(strlen(argv[i])+1); // +1 for NUL terminator byte
strcpy(args->b, argv[i]);
pthread_create(&p[i - 1], NULL, mythread, args);
I need to pas two command line arguments and I tried the following:
#include <stdio.h>
#include <stdlib.h>
void power(int base, int exp){
int res=1;
while(exp!=0){
res *= base;
--exp;
}
printf("Res = %d",res);
}
int main(int argc, char *argv[]) {
if (argc != 3) {
printf("Usage %s arg2 arg2\n(EG: %s 2 3)\n",argv[0],argv[0]);
exit(1);
}else{
power(atoi(argv[1]),atoi(argv[2]));
}
printf("\n");
return 0;
}
Output:
michi#michi-laptop:~$ ./power
Usage ./power arg2 arg2
(EG: ./power 2 3)
michi#michi-laptop:~$ ./power 2 3
Res = 8
Everything until here is ok, but if when save argv[1] and argv[2] in variable like this:
int base = atoi(argv[1]);
int exp = atoi(argv[2]);
I get Segmentation fault
code:
#include <stdio.h>
#include <stdlib.h>
void power(int base, int exp){
int res=1;
while(exp!=0){
res *= base;
--exp;
}
printf("Res = %d",res);
}
int main(int argc, char *argv[]) {
int base = atoi(argv[1]);
int exp = atoi(argv[2]);
if (argc != 3) {
printf("Usage %s arg2 arg2\n(EG: %s 2 3)\n",argv[0],argv[0]);
exit(1);
}else{
power(base, exp);
}
printf("\n");
return 0;
}
But when I use Atoi inside printf everything is OK:
#include <stdio.h>
#include <stdlib.h>
void power(int base, int exp){
int res=1;
while(exp!=0){
res *= base;
--exp;
}
printf("Res = %d",res);
}
int main(int argc, char *argv[]) {
if (argc != 3) {
printf("Usage %s arg2 arg2\n(EG: %s 2 3)\n",argv[0],argv[0]);
exit(1);
}else{
power(atoi(argv[1]), atoi(argv[2]));
}
printf("\n");
return 0;
}
My question is:
is this issue happen because of Atoi?
is this issue happen because I try to access argv[1] and argv[2] and they are not exists when I type ./program?
If I type ./program 2 3 everything is ok, which makes me think that segmentation fault happens because I try to access a memory location which doesn't belong to me at that point.
is this issue happen because I try to access argv[1] and argv[2] and they are not exists when I type ./program?
Yes, the problem is that you are trying to access the command lines arg's before verifying whether they are present or not.
In the second example code snippet, assign the values to the variables base and exp only after making sure that the input is available.
int base;
int exp;
if (argc != 3) {
printf("Usage %s arg2 arg2\n(EG: %s 2 3)\n",argv[0],argv[0]);
exit(1);
}else{
/* Assign the values here, as it is verified that arg's are obtained from cmd line*/
base = atoi(argv[1]);
exp = atoi(argv[2]);
power(base, exp);
}
In the above program it is made sure that I reference the args (argv[1] and argv[2]) only if they are passed as commandline arguments when the program is executed.
is this issue happen because I try to access argv[1] and argv[2] and
they are not exists when I type ./program?
It is because you're not checking for null. argv[1] and argv[2] could be null if no argument is passed in. This causes segmentation fault.
int base = atoi(argv[1]);
int exp = atoi(argv[2]);
Instead, try this
int base = 0;
int exp = 0;
if(argv[1] && argv[2])
{
int base = atoi(argv[1]);
int exp = atoi(argv[2]);
}
Or you could check the argument count to make sure you have 2 arguments passed in.
if(argc > 2)
{
int base = atoi(argv[1]);
int exp = atoi(argv[2]);
}
When you call atoi on argv[ > 0] when there's no argument, you're accessing out of bounds memory, which is Undefined Behavior.
By the C Standard definition, accessing out of bounds memory is Undefined Behavior.
Might Interest you
How dangerous is it to access an array out of bounds?
Undefined, unspecified and implementation-defined behavior
I got this code from an advanced Linux programming book. When I try to execute the code under Linux 64bit environment the value of the which_prime variable gets corrupted (changes to 0) after pthread_join() function call.
In this example why the value of which_prime gets corrupted after running pthread_join?
In general can we use the 4th argument passed to pthread_create function safely inside main even if we call other functions like pthread_join()?
#include <pthread.h>
#include <stdio.h>
/* Compute successive prime numbers (very inefficiently). Return the
Nth prime number, where N is the value pointed to by *ARG. */
void* compute_prime (void* arg)
{
int candidate = 2;
int n = *((int*) arg);
while (1) {
int factor;
int is_prime = 1;
/* Test primality by successive division. */
for (factor = 2; factor < candidate; ++factor)
if (candidate % factor == 0) {
is_prime = 0;
break;
}
/* Is this the prime number we’re looking for? */
if (is_prime) {
if (--n == 0)
/* Return the desired prime number as the thread return value. */
return (void*) candidate;
}
++candidate;
}
return NULL;
}
int main ()
{
pthread_t thread;
int which_prime = 5000;
int prime;
/* Start the computing thread, up to the 5,000th prime number. */
pthread_create (&thread, NULL, &compute_prime, &which_prime);
/* Do some other work here... */
/* Wait for the prime number thread to complete, and get the result. */
pthread_join (thread, (void*) &prime);
/* Print the largest prime it computed. */
printf(“The %dth prime number is %d.\n”, which_prime, prime);
return 0;
}
We've arrived at a point in time where it is no longer safe to convert between an int and a pointer. That's because there are 64-bit systems where a pointer is 64-bits, but an int is only 32-bits.
So assuming 32-bit int and 64-bit pointer, here's what's happening in your code. The second argument to pthread_join is a pointer-to-a-pointer. In other words, you should be passing the address of a pointer (the address of a 64-bit value). Instead, you are passing the address of prime (the address of a 32-bit value). When pthread_join writes the result, it overwrites which_prime, because which_prime follows prime in memory.
To fix the problem, you need to avoid converting between ints and pointers. One way to do that is to avoid using the second parameter of pthread_join, as demonstrated by the following code.
#include <stdio.h>
#include <pthread.h>
#define NUM_THREADS 20
typedef struct
{
int success;
int input;
int output;
} stData;
void *doSomething( void *arg )
{
stData *dataptr = arg;
dataptr->success = 1;
dataptr->output = dataptr->input * 2;
return NULL;
}
int main( void )
{
int i;
pthread_t id[NUM_THREADS];
stData data[NUM_THREADS] = {{0}};
for ( i = 0; i < NUM_THREADS; i++ )
{
data[i].input = i + 1;
pthread_create( &id[i], NULL, doSomething, &data[i] );
}
for ( i = 0; i < NUM_THREADS; i++ )
{
pthread_join( id[i], NULL );
if ( data[i].success )
printf( "thread %2d: input=%2d output=%2d\n", i+1, data[i].input, data[i].output );
else
printf( "thread %2d: failed\n", i+1 );
}
return 0;
}
I'm trying to edit this code to work with ints parameters:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
void* worker (void* param) {
int* nr = (int *) param;
printf ("I got: %d\n",nr);
}
int main (int argc, int *argv[])
{
pthread_t th;
int i;
for(i=1;i<argc;i++){
pthread_create (&th, NULL, worker,(void*)argv[i]);
pthread_join (th, NULL);
}
}
This is not working, smth about pointers, I don't understand. Can anyone explain me? I don't want to use "atoi" function.
For number 5 and 2 I get: -1078000975,-1078000973 and a warning:
11:3: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat=]
printf ("I got: %d\n", nr);
^
A few issues:
argv should be written char * argv[], not int * argv[].
Your (void *) cast in your pthread_create() call is unnecessary.
Your thread function should return a void *.
atoi(), or its more capable cousin, strtol(), is exactly what you're looking for, here. You can either use them, or convert your strings manually, which is suboptimal.
Here's a working version:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void * worker (void * param)
{
char * numstr = param, * endptr;
long num = strtol(numstr, &endptr, 0);
if ( *endptr ) {
printf("Invalid number.\n");
}
else {
printf ("I got: %ld\n", num);
}
return NULL;
}
int main (int argc, char *argv[])
{
pthread_t th;
for ( int i = 1; i < argc; ++i ) {
pthread_create (&th, NULL, worker, argv[i]);
pthread_join (th, NULL);
}
return 0;
}
and some sample output:
paul#horus:~/src/sandbox$ ./trd 5 haha 10
I got: 5
Invalid number.
I got: 10
paul#horus:~/src/sandbox$
If the arguments you recieve are smaller than 10, you can do this:
pthread_create (&th, NULL, worker,(void*)(argv[i][0]-'0'));
This can be done because ASCII numbers begin at 48 ('0' value). So if you receive a '7' (55 ascii number), you can subtract the '0' to get it: 55-48=7.
If the arguments can be 10 or greater, you must use atoi or a self-implementation of that function, as you can not cast from char* to int in C.
There is another problem with your code, you try to print an int*, which is only a variable that contains a memory address. You should recieve it as an int:
void* worker (void* param)
{
int nr = (int) param;
printf ("I got: %d\n",nr);
}
EDIT:
So your code should look like this:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
void* worker (void* param) {
int nr = (int) param;
printf ("I got: %d\n",nr);
}
int main (int argc, char *argv[])
{
pthread_t th;
int i;
for(i=1;i<argc;i++){
pthread_create (&th, NULL, worker,(void*)(argv[i][0]-'0'));
pthread_join (th, NULL);
}
}
It works for me...
You should pass the pointer to the string and then manipulate it.
pthread_create (&th, NULL, worker, argv[i]); //cast is not required
void* worker (void* param) {
char* nr = param ;
Now you got your string in the thread. Get the first character, and convert it to an integer.
int n = nr[0]-'0' ;
printf ("I got: %d\n",n);
}
I'm trying to develop a program in C that will generate a given number of random integers. It is supposed to use a given number of threads to speed this up. I found out that the regular random function won't work with threads and am now using random_r instead. I keep getting a SegFault at the initstate_r function, which doesn't make sense because I'm trying to initialize variables, not access them. Can anyone tell me what I'm doing wrong here? (The initstate_r function needs to stay in the generateRandomNumbers function.)
Here is the code:
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h> // must include stdio for pvm3.h to compile correctly
#include <sys/times.h> /* for times system call */
#include <sys/time.h> /* for gettimeofday system call */
#include <pthread.h>
/*#define DEBUG 1*/
#define RANDOM_SEED 12345678
//The main work routine
//void generateRandomNumbers(long long);
void *generateRandomNumbers(void *);
double getMilliSeconds();
/* The main work routine */
//void generateRandomNumbers(long long int count)
void *generateRandomNumbers(void *arg)
{
struct random_data buf;
int32_t result;
char rand_statebuf;
printf("hold 1\n");
// This is the function that gives me a SegFault
initstate_r(RANDOM_SEED, &rand_statebuf, 128, &buf);
printf("hold 2\n");
long long int* count = (long long int*) arg;
//printf("Count for thread ID# %ld is %lld\n", pthread_self(), *count);
long long int i;
//long int x;
srandom_r(RANDOM_SEED, &buf);
for (i = 0; i < *count; i++) {
random_r(&buf, &result);
#ifdef DEBUG
printf("%ld\n", result);
#endif
}
pthread_exit(NULL);
}
int main(int argc, char **argv)
{
long long int count, newCount;
int numThreads;
//pthread_t *tids;
double timeStart = 0;
double timeElapsed = 0;
if (argc < 3) {
fprintf(stderr, "Usage: %s <n>\n" ,argv[0]);
exit(1);
}
sscanf(argv[1],"%lld",&count); /* lld for long long int */
sscanf(argv[2],"%d",&numThreads);
pthread_t tids[numThreads];
newCount = count/numThreads;
timeStart = getMilliSeconds(); //And we are off
int i;
for (i=0; i<numThreads; i++)
{
pthread_create(&tids[i], NULL, generateRandomNumbers, (void *) &newCount);
//pthread_join(tids[i], NULL);
}
int j;
for (j=0; j<numThreads; j++)
{
pthread_join(tids[j], NULL);
}
//generateRandomNumbers(count);
printf("generated %lld random numbers\n", count);
timeElapsed = getMilliSeconds() - timeStart;
printf("Elapsed time: %lf seconds\n",(double)(timeElapsed/1000.0));
fflush(stdout);
exit(0);
}
The problem is, initstate_r's second param is supposed to be a char*,
You do:
char rand_statebuf;
printf("hold 1\n");
// This is the function that gives me a SegFault
initstate_r(RANDOM_SEED, &rand_statebuf, 128, &buf);
You pass it a pointer to 1 character which meets the requirement for a character pointer, however you need much more space than just one character. It should be:
char rand_statebuf[128];
initstate_r(RANDOM_SEED,rand_statebuf,sizeof(rand_statebuf),&buf);