I am struggling to pass an array of files as an argument to pthread_create function.
FILE *arqvs[arq];
for(int i=1, count=0;i<=arq;i , count ){
changeName(file, i); //change the name of the file based on the index
arqvs[count] = fopen(file, "r");
if(arqvs[count]==NULL){
printf("Erroro:(\n");
exit(1);
}
}
The code above shows how I am creating the array and opening the files in "r" mode. I have done some tests and it seems to work well. Is reads all the files based on the number of the variable arq. The problem comes out when I try to pass the array to the function pthread_create as mentioned above..
Here's the code:
for(int i=0;i<trd; i ){
pthread_create(&thread[i], NULL, funcao, &**arqvs);
}
And here's the function:
void * funcao(void * args){
char voto[2];
FILE *** fileName = (FILE***) args;
while (fgets(voto, sizeof(voto), *fileName[0])) {
printf("%s", voto);
pthread_exit(NULL);
}
This code does not work, and I dont know why. It has been awhile since I programmed in C, so, I would appreciate any hints or answers.
CodePudding user response:
In C, arrays are usually passed to functions/threads by passing a pointer to the first element of the array. If the length is unknown to the called function/thread, then an additional parameter is often passed which specifies the number of elements in the array.
If the number of elements in the array (which is the value of arq
) is known to both threads, then you only need to pass a pointer to the first element of the array. Otherwise, you will also have to pass the number of elements in the array to pthread_create
, for example by instead passing a pointer to a struct
which also contains this information.
Assuming that the number of elements in the array does not have to be passed, you should change the line
pthread_create(&thread[i], NULL, funcao, &**arqvs);
to
pthread_create(&thread[i], NULL, funcao, arqvs);
which is equivalent to:
pthread_create(&thread[i], NULL, funcao, &arqvs[0]);
This is because the array arqvs
automatically decays to a pointer to the first element of the array when used in this context.
Since the array's element type is FILE *
and a pointer to the first element of the array has been passed to the function funcao
, this means that the type of the passed pointer is FILE **
. Therefore, you should change the line
FILE ** fileName = (FILE**) args;
to:
FILE ** fileName = (FILE**) args;
Also, fileName
does not seem like an appropriate name for this pointer. A better name would be something like files
or streams
.
CodePudding user response:
The value (&**argvs
) you're passing in to pthread_create
is a FILE *
. But then in funcao
, you are casting it to a FILE ***
which is not the same, so everything breaks (undefined behavior).
You need to make sure the value you pass in and the value you cast the void *
to are the same type. In your case, it probably makes the most sense to use FILE **
. So you can call pthread_create as:
pthread_create(&thread[i], NULL, funcao, arqvs);
and in funcao, use it as:
FILE ** files = (FILE**) args;
Note that arq
(the size of the array) is lost when you convert the array to a pointer, so you have no good way of knowing how many FILE *
s there are in funcao. It may make more sense to create a struct
that holds both the (pointer to the) array and the array size, and pass a pointer to that to the thread function.
CodePudding user response:
Just pass the array directly, there's no need to use &
. Arrays automatically decay to a pointer when used as function arguments.
for(int i=0;i<trd; i ){
pthread_create(&thread[i], NULL, funcao, arqvs);
}
void * funcao(void * args){
char voto[2];
FILE **fileName = args;
while (fgets(voto, sizeof(voto), fileName[0])) {
printf("%s", voto);
}
pthread_exit(NULL);
}