C Problem mit cast von void pointer zu int

mahatma andi

Cadet 4th Year
Registriert
Jan. 2007
Beiträge
97
Hallo Leute.

Ich bin gerade ein wenig am pthreads anschauen, um multithreading zu lernen in C. Dabei habe ich ein Problem in einem Program, dass für die Zahlen von 0 bis 99 die Wurzel ausrechnen soll und für jede Rechnung einen eigenen Thread starten soll.

Mein Code sieht so aus:
Code:
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<math.h>

#define NUMTHREADS 100


 void *function( void *number){
long newnumber;
newnumber=(long) number;
double *result;
result=(double*) malloc(sizeof(double));

printf("the squareroot of %ld is being calculated\n", newnumber);
*result=(double)sqrt((double)newnumber);

return result;
 }

 int main(){
pthread_t threads[NUMTHREADS];
long number;
long result[NUMTHREADS];
void *exit_status[NUMTHREADS];
int rc;

for(number=0;number<NUMTHREADS;number++){
rc=pthread_create(&threads[number],NULL, function, (void*) number);
if(rc){
printf("there's been an error in creating thread %ld",number);
return 0;
}
pthread_join(threads[number],&exit_status[number]);
}

for(number=0;number<NUMTHREADS;number++){
[B]result[number]=(long)exit_status[number];[/B]
printf("the squareroot of %ld is %ld\n",number,result[number]);
}

return 0;
 }

beim compilieren mit gcc -g -pthread dateiname.c -lm -o dateiname gibt es mir dann den fehler aus, dass auf Zeile 38:20 (fett markiert) folgendes falsch ist:
warning: assignment makes integer from pointer without a cast
exit status sollte ja jetzt der pointer zu einem double sein, den ich von der funktion zurückbekomme, aber als void. Dann müsste ich ja den pointer zu einem pointer zu double casten, da dieser als void zurückgegeben wird ... wie mach ich das dann?

gruss, mahatma
 
Du musst den Pointer den du dir aus dem Array exit_status holst erst dereferenzieren mit *:
result[number] = (long) *exit_status[number];

Wenn er das auch nicht frisst, weil er void* vermutlich nicht dereferenzieren kann:
result[number] = (long) *((double *) exit_status[number]);

Allerdings verstehe ich nicht, wieso du die Wurzel als double berechnest und sie anschließend als long abspeichern willst (zur Ausgabe oder so).
Was du weiterhin nicht vergessen darfst ist, dass zu jedem malloc irgendwo ein free-Aufruf stehen muss.
 
Zuletzt bearbeitet:
Oh shit, danke vielmals!

Das mit dem long ist natürlich quatsch, sollte ein double sein... und dann funktionierts mit dem *((double*)exit_status[number]) ausgezeichnet. Das mit dem long war ein Gehirnaussetzer, wirklich....


sehe ich das richtig, dass (double*) den void pointer von exit_status als pointer zu double castet, dann das äussere * den wert vom pointer aufruft bzw dereferenziert?

und für den free() Befehl (den ich schlicht vergessen habe). Ist der korrekterweise free(exit_status[number]) oder muss ich den wiederum als double casten, damit free weiss, wieviel Speicherplatz befreit werden muss?

also: free((double*)exit_status[number]);


Gruss, mahatma
 
Das mit den Casts und * hast du so richtig verstanden.

Bei free() genügt es, den Pointer als void* zu übergeben, da die Funktion jeden Pointer ohnehin nur als void* sieht (siehe Signatur der Funktion). Es tut aber auch nicht weh, wenn du den Typecast stehenlässt.

Was mir gerade noch auffällt: Du machst dein pthread_join in der selben Schleife, in der du die Threads erstellst. Das heißt, du startest einen Thread und wartest anschließend direkt auf seine Beendigung. Daraus folgt, dass alle gestarteten Threads hintereinander, also sequentiell und nicht parallel, ausgeführt werden.
Du müsstest erst in einer Schleife alle Threads starten und anschließend in einer neuen Schleife auf deren Beendigung warten. Das wird aber in dem Beispiel nicht viel ändern, da ein Thread vermutlich schon fertig ist, bis der nächste gestartet ist. Es gibt einfach zu wenig Arbeit in deiner Thread-Funktion.
 
Zuletzt bearbeitet:
Aso ja, jetzt habe ich das join in die zweite for-Schleife verschoben. Ich bin bei pthread_join noch unsicher, was passiert, wenn der thread der gejoint werden soll schon fertig ist... aber so wie's aussieht, führt das nicht zu Problemen, der Wert wird trotzdem übergeben.

edit: valgrind sagt, dass alles wieder befreit wurde und kein leak möglich sei. I like B)
 
Zuletzt bearbeitet:
Zurück
Oben