error with running multiple thread with C example - c

I have found an example of multi thread programming which help to determine the prime numbers for a given integar n.it will also take number of thread as a input from the user.But the problem is when i try to execute it give me some errors which very hard to solve.Can anyone help?I am newbies at coding so any type of help and advice will be greatly appreciated.
#include <stdio.h>
#include <math.h>
#include <pthread.h> // required for threads usage
#define MAX_N 100000000
#define MAX_THREADS 25
int nthreads, n, prime[MAX_N+1], nextbase; // next sieve multiplier to be used
// lock for the shared variable nextbase
pthread_mutex_t nextbaselock = PTHREAD_MUTEX_INITIALIZER;
// ID structs for the threads
pthread_t id[MAX_THREADS];
// "crosses out" all odd multiples of k
void crossout(int k)
{ int i;
for (i = 3; i*k <= n; i += 2) {
prime[i*k] = 0;
}
}
// each thread runs this routine
void *worker(int tn) // tn is the thread number (0,1,...)
{ int lim,base,
work = 0; // amount of work done by this thread
// no need to check multipliers bigger than sqrt(n)
lim = sqrt(n);
do {
pthread_mutex_lock(&nextbaselock);
base = nextbase;
nextbase += 2;
// unlock the lock
pthread_mutex_unlock(&nextbaselock);
if (base <= lim) {
// don't bother crossing out if base known composite
if (prime[base]) {
crossout(base);
work++; // log work done by this thread
}
}
else return work;
} while (1);
}
main(int argc, char **argv)
{ int nprimes, // number of primes found
i,work;
n = atoi(argv[1]);
nthreads = atoi(argv[2]);
for (i = 3; i <= n; i++) {
if (i%2 == 0) prime[i] = 0;
else prime[i] = 1;
}
nextbase = 3;
// get threads started
for (i = 0; i < nthreads; i++) {
pthread_create(&id[i],NULL,worker,i);
}
for (i = 0; i < nthreads; i++) {
pthread_join(id[i],&work);
printf("%d values of base done\n",work);
}
nprimes = 1;
for (i = 3; i <= n; i++)
if (prime[i]) {
nprimes++;
}
printf("the number of primes found was %d\n",nprimes);
}
I have the following error while compiling:
In function ‘worker’:
Primes.c:67:12: warning: return makes pointer from integer without a cast [enabled by default]
else return work;
^
Primes.c: In function ‘main’:
Primes.c:88:7: warning: passing argument 3 of ‘pthread_create’ from incompatible pointer type [enabled by default]
pthread_create(&id[i],NULL,worker,i);
^
In file included from Primes.c:15:0:
/usr/include/pthread.h:244:12: note: expected ‘void * (*)(void *)’ but argument is of type ‘void * (*)(int)’
extern int pthread_create (pthread_t *__restrict __newthread,
^
Primes.c:88:7: warning: passing argument 4 of ‘pthread_create’ makes pointer from integer without a cast [enabled by default]
pthread_create(&id[i],NULL,worker,i);
^
In file included from Primes.c:15:0:
/usr/include/pthread.h:244:12: note: expected ‘void * __restrict__’ but argument is of type ‘int’

using: gcc -c -Wall -Wextra -Wconversion -std=gnu99 %f
where %f is the name of the file being compiled
The compiler output the following messages.
I added some commentary for each message that should point you to how to fix the problem.
compiler warning message:
:28:14: warning: conversion to 'int' from 'double' may alter its' value [-Wconversion]
lim = sqrt(n);
The function: sqrt() returns a 'double' but 'lim' is declared a 'int'
Suggest: cast the returned value to 'int'
lim = (int)sqrt(n);
compiler warning message:
:43:12: warning: return makes pointer from integer without a cast [enbled by default]
else return work;
the return type from the worker() function is void*
always exit the worker() function by:
pthread_exit( &work );
compiler warning message:
:24:18: warning: unused parameter 'tn' [-Wunused-parameter]
means the parameter 'tn' is not used. fix this by inserting in that function the line:
(void)tn;
compiler warning message:
47:1: warning: return type defaults to 'int' [enabled by default]
The signature of the main() function is not correct. without using the environment parameter, (almost never used), there are only 2 valid main() signatures and one optional signature.
use the correct signature for what your program needs.
int main( void )
int main( int argc, char *argv[] )
int main() // optional signature
compiler warning message:
50:4: warning: implicit declaration of function 'atoi' [-Wimplicit-function-declaration]
means the header file: stdlib.h has not been #include'd suggest inserting at top of file:
#include <stdlib.h>
compiler warning message:
61:7: warning: passing argument 3 of 'pthread_create' from incompatible pointer type [enabled by default]
means the third parameter to the function: pthread_create() was not a void pointer. suggest:
pthread_create(&id[i],NULL,worker,(void*)&i);
compiler warning message:
67:7: warning: passing argument 2 of 'pthread_join' from incompatible pointer type [enabled by default]
means the variable 'work' should be declared, in file global space, not in the thread function, as:
void * work;
there are other compiler warning messages output, but the above will eliminate them.
I.E. always start with the first compiler message, fix that, then re-compile. then fix the new first message.
Most of the problems with the syntax of the code could have been avoided by paying attention to the man pages for the system functions that were called in the posted code.
Note: the crossout() functions' logic is not correct. the code needs to start at k+k, continue until k<=n and step by k+=k I.E.
for( int k=i+i; k<(n+1); k+=k )
the code seems to be trying to implement a eratosthenes sieve for prime numbers google for the details.
unless your required to use threads, don't, they will just slow things down due to all the context swapping, etc.
this code logic:
for (i = 3; i <= n; i++)
{
if (i%2 == 0) prime[i] = 0;
else prime[i] = 1;
}
seems to be wrong, for one thing, the array prime[] will be initially all 0 because it is in the file global space. As far as I can tell, that code block is not needed at all.
because the work variable will be in the file global space, suggest an array of
void* work[ nthreads ];
then have the thread function: worker() actually use the passed parameter to select which of the entries in the array to be updating.

Related

Regarding passing pointers as arguments

I am trying to code a basic zero threshold function. such that if the value of the array element is greater than zero must remain same else it must be zero. But my problem is with passing the array values from main to the function using pointers. Here's the snippet. im is the input array and im2 is the array to store result. t is the threshold which is 0 and m is the order. On passing the input array from main to thresh function. I just checked the values of im in thresh function but all were showing 0, as commented in code below, instead of original values. where am i going wrong??
int thresh(double *im[], double *im2[], int t, int m)
{
int i, j;
printf("im:%f", im[0]); //here i am getting output as zero instead of 1
for (i = 0; i < m; i++)
{
if (im[i] > t)
im2[i] = im[i];
else
im2[i] = 0;
}
return 0;
}
int main()
{
float im[4] = { 1,-2,3,-4 };
float im2[4];
int th = 0;
thresh((float*)im, (float*)im2, th, 2);
getch();
return 0;
}
Turn on compiler warnings and read them. They are there to help. This is what I got on compilation:
$ gcc main.c
main.c: In function ‘thresh’:
main.c:10:23: warning: comparison between pointer and integer
if (im[i] > t)
^
main.c: In function ‘main’:
main.c:24:12: warning: passing argument 1 of ‘thresh’ from incompatible pointer type [-Wincompatible-pointer-types]
thresh((float*)im, (float*)im2, th, 2);
^
main.c:4:5: note: expected ‘double **’ but argument is of type ‘float *’
int thresh(double *im[], double *im2[], int t, int m)
^~~~~~
main.c:24:24: warning: passing argument 2 of ‘thresh’ from incompatible pointer type [-Wincompatible-pointer-types]
thresh((float*)im, (float*)im2, th, 2);
^
main.c:4:5: note: expected ‘double **’ but argument is of type ‘float *’
int thresh(double *im[], double *im2[], int t, int m)
^~~~~~
So there is some stuff to fix.
First of, the prototype for thresh should be int thresh(double *im, double *im2, int t, int m) or even better int thresh(const double *im, double *im2, int t, int m)
Second, why are you mixing float and double? Stick to one, and stick to double unless you have a really good reason.

"segmentation error (core dumped)" Using function and pointers

I am learning functions in C and having following problem with so many warnings :-(
code is as follows
#include <stdio.h>
void main(){
int a,c;
char *b; // declaring a pointer
char string[100]="something";
b = string; // assigning a pointer.. doing
printf("\n %s \n\n %s",string,*b); // doing this as a verification of the pointer, which is good - no seg faults
printf("Enter a and c:-");
scanf("%d %d",&a,&c);
find(a,c,*b);
printf("%s",*b);//segmentation fault core dumped:-'(
}
void find(int x, int y,char *b){
if(x>y)
*b = "a is greater than b";
else if(x=y)
*b = "both the values are equal";
else
*b = "b is greater than a";
}
warnings while compiling:--
function.c: In function ‘main’:
function.c:7:2: warning: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘int’ [-Wformat=]
printf("\n %s \n\n %s",string,*b); /*doing this jus to check is pointer working but no it is *not.segmentation error here "core dumped":-'(
^
function.c:12:2: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
printf("%s",*b);//segmentation fault core dumped:-'(
^
function.c: At top level:
function.c:14:6: warning: conflicting types for ‘find’ [enabled by default]
void find(int x, int y,char *b){
^
function.c:11:2: note: previous implicit declaration of ‘find’ was here
find(a,c,*b);
^
function.c: In function ‘find’:
function.c:16:6: warning: assignment makes integer from pointer without a cast [enabled by default]
*b = "a is greater than b";
^
function.c:18:6: warning: assignment makes integer from pointer without a cast [enabled by default]
*b = "both the values are equal";
^
function.c:20:6: warning: assignment makes integer from pointer without a cast [enabled by default]
*b = "b is greater than a";
while running
segmentation error (core dumped)
Working cod:=---- with the help of community
#include <stdio.h>
#include <malloc.h>
void main(){
int a,c;
char *b =(char *)malloc(100);
char string[100]="something";
b = &string;
printf("\n %s \n\n %s",string,b);
printf("Enter a and c:-");
scanf("%d %d",&a,&c);
find(a,c,*b);
printf("\n%s",b);
}
void find(int x, int y,char *b){
if(x>y)
b = "a is greater than b";
else if(x=y)
b = "both the values are equal";
else
b = "b is greater than a";
}
output:-
something
something
enter a and c:-
10
20
something
**
means still it is not updating the value in the function...
**
I fix your code in less than a minute.No warnings and probably works (I don't speaking for logical problems).This means that your warnings were common mistake that even an experienced engineer might do.However a smart engineer will use warnings to fix these warnings.
#include <stdio.h>
#include <malloc.h>
void find(int, int,char*);
int main(){
int a,c;
char *b = NULL;
char string[100]="something";
b = &string[0];
printf("\n %s \n\n %s",string,b);
printf("Enter a and c:-");
scanf("%d %d",&a,&c);
find(a,c,b);
printf("\n%s",b);
return 0;
}
void find(int x, int y,char *b){
if(x>y)
b = "a is greater than b";
else if(x == y)
b = "both the values are equal";
else
b = "b is greater than a";
}
If you check this , you will see that there is no warning now.
Regarding on your effort to learn , I would try to explain warnings and try to estimate and give you a big picture of what those warnings would result.
warning: return type of ‘main’ is not ‘int’
-Here you take the answers in why we prefer to return int in main.
int main vs void main
warning: suggest parentheses around assignment used as truth value
-This is the worst error you have. = is for asign , == is for comparison
Difference between = and ==
The other too errors ,
conflicting type
and
implicit declaration
means that preprocessor of your compiler reached function invocation ( find(a,c,*b); ) before the declaration of the function.So one compiler might fix that and auto resolve this while another compiler might have an error.That's why preprocessor check firstly the header file , but since you don't have a header file (that's bad) , you should have a declaration of the function before you invoke this.
Whilst you fix that you would receive a warning ,
warning: passing argument 3 of ‘find’ makes pointer from integer
without a cast
This means that you are trying to pass the pointer of the pointer. b was a pointer at the first place , which hold the address of the first element of your char array.So y should have pass this without *.
THIS is a very good example on the question Why we don't ignore error
.Because an error about implicit declaration of a function , led as to discover another error , more significant than the first , that was hiding under the first warning.
Another note is that you don't need to malloc there.You malloc when you want to allocate an amount of memory on the heap and keep it alive before you free it.
PS:I hope I help and I hope you also take some benefit out of these.If you have any question , do not hesitate to comment(better in chat , to avoid spam in the community)
Thank you.

How to implement map that associates a name with void function in C?

After reading Structure and Interpretation of Computer Programs (SICP) I decided to find a way to implement some of these functional programming techniques using C. I tried to write a program that makes a pair whose first argument is a name of the function and second arg is any function that takes one arg and returns one arg. Using implementation below I was expecting to see
an output like:
fact(7) = 5040
fib(7) = 13
but instead I am getting
fact(7) = 5040
fib(7) = 0
along with warnings
$ cc map.c
map.c: In function ‘main’:
map.c:41:17: warning: assignment from incompatible pointer type [enabled by default]
maps[0].f_ptr = &fact;
^
map.c:43:17: warning: assignment from incompatible pointer type [enabled by default]
maps[1].f_ptr = &fib;
^
map.c:47:7: warning: passing argument 1 of ‘maps[i].f_ptr’ makes pointer from integer without a cast [enabled by default]
ans = (int) maps[i].f_ptr((int) num);
^
map.c:47:7: note: expected ‘void *’ but argument is of type ‘int’
map.c:47:13: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
ans = (int) maps[i].f_ptr((int) num);
^
map.c:52:7: warning: passing argument 1 of ‘maps[i].f_ptr’ makes pointer from integer without a cast [enabled by default]
ans2 = (int) maps[i].f_ptr((int) num);
^
map.c:52:7: note: expected ‘void *’ but argument is of type ‘int’
map.c:52:14: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
ans2 = (int) maps[i].f_ptr((int) num);
during compilation. Looking at the code I don't see the problem but then again I haven't used C in quite some time. Is there a better way to implement such a construct and why is fib(7) printing a 0 instead of 13?
Here's my code:
struct Map
{
char* name;
void* (*f_ptr)(void*);
};
int fact(int a) {
if (a == 0)
return 0;
if (a == 1)
return 1;
return a * fact (a-1);
}
int fib(int a) {
if (a == 0)
return 0;
if (a == 1)
return 1;
return fib(a-1) + fib(a-2);
}
int findFunc (char* str, struct Map map)
{
if (map.name == str)
return 1;
return 0;
}
int main()
{
int i = 0;
int ans = 0;
int ans2 = 0;
int num = 7;
struct Map maps[2];
maps[0].name = "fact";
maps[0].f_ptr = &fact;
maps[1].name = "fib";
maps[1].f_ptr = &fib;
for (i; i < (sizeof(maps)/sizeof(maps[0])); i++) {
if (findFunc("fact", maps[i]))
ans = (int) maps[i].f_ptr((int) num);
}
for (i; i < (sizeof(maps)/sizeof(maps[0])); i++) {
if (findFunc("fib", maps[i]))
ans2 = (int) maps[i].f_ptr((int) num);
}
printf("fact(%d) = %d\n", num, ans);
printf("fib(%d) = %d", num, ans2);
return 0;
}
String comparisons
This is not how you do string comparison in C.
if (map.name == str)
This is how you do string comparison in C.
if (0 == strcmp(map.name, str))
Because strings in C are just pointers to characters, map.name == str checks if map.name and str are identical pointers (point to the same block of memory), not whether what they point to is the same.
for loops
Your code is probably reporting fib(7) = 0 because it's failing to find fib. One possible culprit is the string comparison issue I mentioned. However, your for loop syntax is also odd:
for (i; i < (sizeof(maps)/sizeof(maps[0])); i++) {
You don't set i to anything, so this means, "Starting from wherever i happens to be, do the following..."
To loop over all of maps, use this:
for (i = 0; i < (sizeof(maps)/sizeof(maps[0])); i++) {
type warnings
As #alk said in a comment, the reason you're getting all of those warnings is because you've declared a function type of void* (*f_ptr)(void*);, even though your functions are int (*)(int). If you want to keep using void* to allow different types, and you're careful enough with your types to make this work, then you can add casts to silence the warnings.
maps[0].f_ptr = (void *(*)(void*)) &fact;
ans2 = (int) maps[i].f_ptr((void*) num);
Etc.
Better implementations?
A "real" implementation of mapping functions to names would use a hash table, instead of linearly searching for matching names. Implementing a hash table in C would add complexity and may not be worth it for this exercise.
but instead I am getting
[...]
fib(7) = 0
The code misses to initialise i to 0 for the 2nd for-loop.

Cannot Use Printf!?! (while performing hashing algorithm using mhash)

I am using Mhash and I would like to print the length of my blocksize for debugging purposes, but I keep getting an error every time I try to compile
Any suggestions on how I can fix this error?
Here is my code:
#include <mhash.h>
#include <stdio.h>
#include <string.h>
// 0x12e6bc6e68c3b9506e6668db6b7224f894fab073728fc179 (TIGER192) (48)
int main()
{
char password[] = "Jefe";
int keylen = 4;
char data[] = "what do ya want for nothing?";
int datalen = 28;
MHASH td, td2;
unsigned char *mac, *mac2;
int i, j;
td = mhash_hmac_init(MHASH_TIGER192, password, keylen, mhash_get_hash_pblock(MHASH_TIGER192));
mhash(td, data, datalen);
mac = mhash_hmac_end(td);
printf("0x");
for (i = 0; i < mhash_get_block_size(MHASH_TIGER192); i++)
{
printf("%.2x", mac[i]);
}
printf("\n");
// int length = strlen(mac);
// printf(length);
// int length = 5;
// printf(length);
exit(0);
}
I run the program with the following commands:
hb2#hb1:~/Desktop$ gcc -o hashexample hashexample.c -lmhash
hb2#hb1:~/Desktop$ ./hashexample
0x12e6bc6e68c3b9506e6668db6b7224f894fab073728fc179
And it runs successfully, but when I try to print the length of the hashed result, I get the following error!!? Any ideas on why?
// int length = strlen(mac);
// printf(length);
hb2#hb1:~/Desktop$ gcc -o hashexample hashexample.c -lmhash
hashexample.c: In function ‘main’:
hashexample.c:33:2: warning: passing argument 1 of ‘printf’ makes pointer from integer without a cast [enabled by default]
/usr/include/stdio.h:363:12: note: expected ‘const char * __restrict__’ but argument is of type ‘int’
hashexample.c:33:2: warning: format not a string literal and no format arguments [-Wformat-security]
At first, I thought it was because I thought I was using strlen incorrectly?! But even when I try to do a simple printf of an integer, I still get an error:
// int length = 5;
// printf(length);
hb2#hb1:~/Desktop$ gcc -o hashexample hashexample.c -lmhash
hashexample.c: In function ‘main’:
hashexample.c:35:2: warning: passing argument 1 of ‘printf’ makes pointer from integer without a cast [enabled by default]
/usr/include/stdio.h:363:12: note: expected ‘const char * __restrict__’ but argument is of type ‘int’
hashexample.c:35:2: warning: format not a string literal and no format arguments [-Wformat-security]
Thanks for your help in advance!
Check the man page for printf(). The first argument is a const char *. You're passing an int.
That's what the warning says too:
warning: passing argument 1 of ‘printf’ makes pointer from integer without a cast [enabled by default]
You wanted:
printf("%d", length);
You need the format string to specify that an int is going to be printed.

Getting warning from C math library's pow function

I have the following function in my code:
int numberOverflow(int bit_count, int num, int twos) {
int min, max;
if (twos) {
min = (int) -pow(2, bit_count - 1); \\ line 145
max = (int) pow(2, bit_count - 1) - 1;
} else {
min = 0;
max = (int) pow(2, bit_count) - 1; \\ line 149
}
if (num > max && num < min) {
printf("The number %d is too large for it's destination (%d-bit)\n", num, bit_count);
return 1;
} else {
return 0;
}
}
At compile time I get the following warning:
assemble.c: In function ‘numberOverflow’:
assemble.c:145: warning: incompatible implicit declaration of built-in function ‘pow’
assemble.c:149: warning: incompatible implicit declaration of built-in function ‘pow’
I'm at a loss for what is causing this... any ideas?
You need to include math.h
And why exactly do we get this warning?
From the wording of your warnings it looks like you are using gcc? Maybe it is worth to try another compiler, namely clang. This one tells me:
test-pow.c:15:18: warning: implicitly declaring C library function 'pow' with type 'double (double, double)' [-pedantic]
test-pow.c:15:18: note: please include the header <math.h> or explicitly provide a declaration for 'pow'

Resources