Confusing clone passing down argument - c++

So basically I am solving the famous "Philosopher dining" problem, 5 philosopher is generating out using clone. The point is I want each philosopher to hold a id (from 0 to 4). I plan to do it using clone passing down argument. Here is the code (I omit some sub function)
void philoshopher(void* arg)
{
int i = &arg;
while (TRUE)
{
printf("Philosopher %d is thinking", i);
take_forks(i);
printf("Philosopher %d is eating", i);
sleep(2);
put_forks(i);
}
}
int main(int argc, char **argv)
{
int i;
int a[N] = {0,1,2,3,4};
void* arg;
/*
struct clone_args args[N];
void* arg = (void*)args;
*/
if (sem_init(&mutex, 1, 1) < 0)
{
perror(NULL);
return 1;
}
for (i=0;i<N;i++)
{ if (sem_init(&p[i], 1, 1) < 0)
{
perror(NULL);
return 1;
}
}
int (*philosopher[N])() ;
void * stack;
for (i=0; i<N; i++)
{
if ((stack = malloc(STACKSIZE)) == NULL)
{
printf("Memorry allocation error");
return 1;
}
int c = clone(philosopher, stack+STACKSIZE-1, CLONE_VM|SIGCHLD, &a[i]);
if (c<0)
{
perror(NULL);
return 1;
}
}
//Wait for all children to terminate
for (i=0; i<4; i++)
{
wait(NULL);
}
return 0;
}
After compile out, I get this error:
passing argument 1 of ‘clone’ from incompatible pointer type [enabled by default]
expected ‘int (*)(void *)’ but argument is of type ‘int (**)()’
I also try to cast this to a void pointer but still same result:
void* arg;
....
arg = (void*)(a[i]);
int c = clone(...., arg);
Anyone know how to fix this. Thanks for your help.

You aren't declaring your function pointer correctly. It should look like this:
int (*philosopher[N])(void*);
Basically when you're declaring function pointers you have to specify the argument type, because pointers to functions that accept different types are (thankfully!) incompatible with each other.
I think you also need to remove the & before a[i] in the function call. That's giving you a pointer to a function pointer, and it just expects a plain function pointer apparently.

Related

g++ error invalid conversion from ‘void*’ to ‘info*’ [-fpermissive],error: invalid conversion from ‘void*’ to ‘void* (*)(void*)’ [-fpermissive]

i'm trying to parallelize the sum of Leibniz to approximate PI using pthreads. When i run this code with latest version of g++ these 2 errors appear and i really dont understand why, and i'm compiling like this:
g++ pi2.cpp -o pi2 -lpthread
error invalid conversion from ‘void*’ to ‘info*’ [-fpermissive]
error: invalid conversion from ‘void*’ to ‘void* (*)(void*)’ [-fpermissive]
Here is my code:
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define top 1000000000
struct info
{
int inicio;
int fin;
double pi;
};
int leibniz(void *ap2){
struct info *ap;
int start, end, i;
ap = ap2;
start = ap -> inicio;
end = ap -> fin;
double x = 0.0;
double deno = 2*start + 1.0;
double nume = 1.0;
int diff = end - start;
for (i = 0; i < diff; ++i)
{
x += nume/deno;
deno += 2;
nume = -nume;
}
ap -> pi = x*4.0;
}
int main(int argc, char const *argv[])
{
int i, cont, rango;
double pi;
int numHilos = 2;
char *check = "";
if (argc >= 2)
{
numHilos = (int)strtol(argv[1], &check, 10);
if (strcmp("", check) != 0)
{
printf("Entrada invalida\n");
}
}
rango = top/numHilos;
cont = 0;
struct info array[numHilos];
for (i = 0; i < numHilos; ++i)
{
array[i].inicio = cont;
array[i].fin = rango;
cont = rango;
rango = rango + (top/numHilos);
}
pthread_t hilos[numHilos];
int r, j, *retval;
for (i = 0; i < numHilos; ++i)
{
r = pthread_create(&hilos[i], NULL, (void *)*leibniz, (void *)&array[i]);
if (r != 0)
{
perror("Error al crear el hilo");
exit(-1);
}
}
for (j = 0; j < numHilos; ++j)
{
r = pthread_join(hilos[j], (void **)&retval);
}
for (i = 0; i < numHilos; ++i)
{
pi = pi + array[i].pi;
}
printf("pi: %2.12f \n", pi);
}
Error 1: error invalid conversion from ‘void*’ to ‘info*’
Unlike C, C++ will not allow you to simply assign void * to anything you want. You have to tell the compiler that you really mean it, and that you aren't making a horrible mistake by casting it.
So
ap = static_cast<info*>(ap2);
Error 2: error: invalid conversion from ‘void*’ to ‘void* ()(void)’
Exactly the same problem, but here it's easier. pthread_create expects void *(*start_routine) (void *), not void * so once you fix an even nastier bug you haven't seen yet, int leibniz(void *ap2) claims to return int but never does resulting in an ill formed program, all of the casting woes go away.
int leibniz(void *ap2)
becomes
void* leibniz(void *ap2)
and must return something. You don't care what, so place
return NULL;
at the end of the function.
leibniz now exactly matches void *(*start_routine) (void *), so
r = pthread_create(&hilos[i], NULL, &leibniz, &array[i]);
in tje beginning: ap=ap2->void* to info*
r=pthread_create(&hilos[i], NULL, (void*)leibniz, &array[i])->void to void(*)()
pthread_create get as 3rd parameter a pointer to a function.

Confusion about pointer to an array as a function parameter

In my textbook about c++ I have the following code example:
using std::cout;
using std::endl;
int main() {
int aArr[4] = { 3,4,2,3 };
int bArr[3] = { 2,3,1 };
cout << "Append: " << endl;
printArray(aArr, 4); cout << " + "; printArray(bArr, 3);
int* cArr = append(&aArr, bArr);
cout << " = "; printArray(cArr, 7); cout << endl;
return 0;
}
Does the "&" symbol in front of "aArr" in the call to append in main mean that the address of aArr is passed, or that a reference to aArr is passed.
The question then asks for me to implement a function append which takes two arrays: the first array (in the first argument) of size 4 by array pointer and the second array (in the second argument) of size 3 by reference and returns a pointer to an array of size 7. I have declared that function as (in the appropriate header file)
int* append( int foo[4], int (&secondArray) [3] );
Has the author perhaps misplaced the order of the "&" symbol in the append method (that it should be in front of "bArr")?
The compiler can help you out in cases like this.
Lets assume that this is the function prototype for your append function:
int* append( int foo[4], int (&secondArray) [3]);
I can test this out with this simple bit of code:
int* append( int foo[4], int (&secondArray) [3])
{
return 0;
}
int main() {
int aArr[4] = { 3,4,2,3 };
int bArr[3] = { 2,3,1 };
int* cArr = append(&aArr, bArr);
return 0;
}
But the compiler doesn't like this, failing with this error:
test.cpp(9): error C2664: 'int *append(int [],int (&)[3])':
cannot convert argument 1 from 'int (*)[4]' to 'int []'
As you can see it doesn't like the &aArr argument 1 at line 9 as it does not match the argument 1 defined by the function at line 1. From the error message it is even nice enough to give a reason why it thinks they don't line up.
Now using the hint from the compiler it is clear the function should in fact look like this:
int *append(int (*foo)[4], int secondArray[3])
{
return 0;
}
int main() {
int aArr[4] = { 3,4,2,3 };
int bArr[3] = { 2,3,1 };
int* cArr = append(&aArr, bArr);
return 0;
}
With that change the compiler is happy to accept the code as correct.
Now comparing the two you can see the difference is in the first case the first argument was passed as an array of 4 integers, whereas in the second case it is passed as the address of an array of four integers.
Just from the english you can tell these are two very different things.
EDIT: Here is an extension of that example that shows how to access the data inside the function.
#include <stdio.h>
int *append(int (*foo)[4], int secondArray[3] )
{
int *foo1 = *foo;
for (int i = 0; i < 4; ++i)
{
printf("foo: %d\n", foo1[i]);
}
for (int j = 0; j < 3; ++j)
{
printf("secondArray: %d\n", secondArray[j]);
}
return 0;
}
int main() {
int aArr[4] = { 3,4,2,3 };
int bArr[3] = { 12,13,11 };
int* cArr = append(&aArr, bArr);
return 0;
}
Compiling an running this code produces this output:
foo: 3
foo: 4
foo: 2
foo: 3
secondArray: 12
secondArray: 13
secondArray: 11

why cannot pass parameter like this?

I have a function:
int getCaseNum(float isovalue,float *F,int **point,int *dims,float *F_value)
{
int digtial_point[8];
int case_num=0;
int i = 0;
for(i=0;i<8;i++)
{
F_value[i] = F[GetPointIndex(point[i],dims)];
if(F_value[i]>isovalue)
{
digtial_point[i] = 1;
case_num = case_num + powf(2,i);
}
else
{
digtial_point[i] = 0;
}
}
return case_num;
}
Then I want to call this function in another function like this:
int pointID[8][3];
int case_num = getCaseNum(isovalue,F,pointID,dims,F_value);
However, when I compile my code, it says:
/Users/liyuanliu/Documents/lecture/sicvis/final_6b/mc510/proj6B.cxx:862:24: error:
no matching function for call to 'getCaseNum'
int case_num = getCaseNum(isovalue,F,pointID,dims,F_value);
^~~~~~~~~~
/Users/liyuanliu/Documents/lecture/sicvis/final_6b/mc510/proj6B.cxx:816:5: note:
candidate function not viable: no known conversion from 'int [8][3]' to
'int **' for 3rd argument
int getCaseNum(float isovalue,float *F,int **point,int *dims,float *F_value)
^
Why this happens ? Cannot I pass parameter like this?
// Create a dynamic 2D int array
int **pointID=new int*[8];
for(int i=0;i<8;i++) {
pointID[i]=new int[3];
}
int case_num=getCaseNum(isovalue,F,pointID,dims,F_value);
you need to get a pointer to first entry in 2D array.
Since array is contiguous, you can use below logic to iterate
int getCaseNum(float isovalue,float *F,int* point,int *dims,float *F_value)
{
for (i = 0; i < 24; i++)
{
cout << *(point+i*sizeof(int));
}
}
caller:
int case_num = getCaseNum(isovalue,F,&pointID[0][0],&dims,F);

passing an array of structs to a function and changing it through the fucntion

so this is my code but it wont compile for some reason.
Error 3 error C2036: 'pjs *' : unknown size
Error 4 error C2100: illegal indirection
Error 5 error C2037: left of 'size' specifies undefined struct/union 'pjs'
void initArray(struct pjs* array)
{
(*array[1]).size = 1;
}
struct pjs{
char* name;
int size;
int price;
};
int main(int argc , char** argv)
{
struct pjs array[10];
initArray(array);
system("PAUSE");
return (0);
}
Following may help:
struct pjs{
char* name;
int size;
int price;
};
// safer to use one of the following declaration
// void initArray(pjs *array, std::size_t size) // simpler
// void initArray(pjs (&array)[10]) // more restrictive but unintuitive syntax
void initArray(pjs* array)
{
array[1].size = 1;
}
int main()
{
pjs array[10];
initArray(array);
}
Definition of pjs should be given before to use it (or requiring its size).
array[1] is a pjs so *array[1] is illegal (as pjs no have operator*)
That simply should be
array[1].size = 1;
Correct your 1st statement of initArray to :
array[1].size = 1;
and cut paste the struct declaration to before the function.
If you want to initialize the entire array, you need to pass the array and a size to initArray.
int main(int argc , char** argv)
{
struct pjs array[10];
initArray(array, sizeof(array)/sizeof(array[0]));
system("PAUSE");
return (0);
}
and then, initialize each object the array as:
void initArray(struct pjs* array, size_t size)
{
for (size_t i = 0; i < size; ++i )
{
array[i].size = 1;
array[i].price = 0; // Or whatever makes sense
array[i].name = malloc(1); // Or whatever makes sense.
}
}

passing pointer to function and using realloc

I want to pass a pointer to a function which will call a second function that will use realloc.
The issue is that realloc is returning NULL.
I don't know if the mistake is in the numbers of * in the function call or something else.
Could you please help me ?
The code:
int main(){
// some code.
clause_t* ptr; //clause_t is a structure i declared.
//Some work including the initial allocation of ptr (which is working).
assignLonely(matSAT, ic.nbClause, ic.nbVar, ptr); //the issue is here.
//Some other work
}
void assignLonely(int** matSAT, int nbClause, int nbVar, clause_t* ptr)
{
int i = 0, j = 0;
int cpt = 0;
int indice = -1;
for (i = 0; i < nbClause ; ++i)
{
j = 0;
cpt = 0;
while((j < nbVar) && (cpt < 2))
{
if (matSAT[i][j] != 0)
{
cpt++;
}
else
{
indice = j;
}
if (cpt < 2)
{
deleteClause(indice, &ptr);
}
j++;
}
}
}
void deleteClause(int indiceClause, clause_t** ptr)
{
int i = indiceClause;
int nbElt = sizeof((*ptr))/sizeof((*ptr)[0]);
int tailleElt = sizeof((*ptr)[0]);
while(i+1 < nbElt)
{
(*ptr)[i] = (*ptr)[i+1];
i++;
}
*ptr = (clause_t*)realloc(*ptr, (nbElt-1)*tailleElt);
if (*ptr == NULL)
{
fprintf(stderr, "Erreur reallocation\n");
exit(EXIT_FAILURE);
}
}
You have to declarae function assignLonely similarly to function deleteClause like
void assignLonely(int** matSAT, int nbClause, int nbVar, clause_t** ptr);
if you want that changes of ptr in the function would be stored in the original object in main.
Also take into account that this statement
int nbElt = sizeof((*ptr))/sizeof((*ptr)[0]);
is wrong.
Expression sizeof((*ptr)) will return the size of the pointer. Pointers do not keep information about how many elements in arrays they point to.
So expression
(nbElt-1)
can be equal to zero or even be negative.