2017-03-07 2 views
0

Ich habe ein Problem mit einer pid_t durch Verweis als void-Zeiger übergeben, und typecasting zurück zu einem pid_t. Mein Code ist wie folgt:void pointer typecasting zu pid_t falsch

typedef void * ProcessHandle_t; 

void createProcess(ProcessHandle_t * processHandle) 
{ 
    pid_t newTask = fork(); 

    if(newTask != 0) 
    { 
     /* Parent process */ 
     /* Return a process handle for the main task to use */ 
     *processHandle = &newTask; 
     printf("pid_t output 1: %d\n", *((pid_t *)*processHandle)); 
    } else 
    { 
     while(1){ 
      printf("Child running\n"); 
     } 
    } 

} 

void deleteProcess(ProcessHandle_t processHandle) 
{ 
    pid_t deleteTask = *((pid_t *)processHandle); 

    printf("pid_t output 3: %d\n", deleteTask)); 

    kill(deleteTask, SIGKILL); 
} 

int main() 
{ 
    ProcessHandle_t processHandle; 

    createProcess(&processHandle); 

    printf("pid_t output 2: %d\n", ((pid_t *)*processHandle)); 

    deleteProcess(processHandle); 

    printf("Parent exiting\n"); 

} 

Und meine Ausgabe lautet:

pid_t output 1: 19876 
pid_t output 2: 19876 
pid_t output 3: 493972479 
Parent exiting 

Aber ich habe keine Ahnung, warum. Wenn ich die gleiche Art von Dereferenzierung mit Ints mache, funktioniert es, aber ich bekomme einen wirklich seltsamen Wert, wenn ich dasselbe für pid_t mache.

Gibt es einen bestimmten Grund, warum dies nicht mit pid_t funktioniert, aber mit anderen Variablentypen funktioniert?

+2

Nicht wirklich eine Antwort auf Ihre Frage, aber diese Art von Kopfschmerzen sind genau, warum Sie Pointer-Semantik nicht hinter einem Typedef verstecken sollten. Wenn Ihre "Abstraktion" Ihren Code zu brechen beginnt, ist das eine schlechte Abstraktion. – StoryTeller

+0

Sollte nicht '* ((pid_t *) processHandle)' 'pid_t) processHandle' in' deleteProcess' sein? – DyZ

+3

Wenn Sie sich die Mühe machen, einen Typedef hinzuzufügen, warum nicht 'typedef ptr_t * ProcessHandle_t;'? Es ist wohl sowohl klarer als auch wartungsfreundlicher. Oder noch besser, vergiss den Typdef und vergiss die Indirektion ... und benutze einfach das Original 'ptr_t' wie es ist! – paulsm4

Antwort

0

Denken Sie daran, dass lokale Variablen den Gültigkeitsbereich verlassen, sobald die Funktion, in der sie definiert wurden, zurückgegeben wird.

In der createProcess Funktion haben Sie

*processHandle = &newTask; 

Hier können Sie *processHandle Punkt zum lokal VariablenewTask machen.

Wenn createProcess zurückgekehrt sind, der Speicher belegte die zuvor von dem newTask Variable nicht mehr „existieren“ (eigentlich wird es durch den nächsten Funktionsaufruf wieder verwendet werden), können Sie mit einem vagabundierenden Zeiger zu verlassen.

Die Dereferenzierung dieses Zeigers führt zu undefiniertem Verhalten!

Wenn Sie die Inhalte von newTask mit Zeigern kopieren, dann müssen Sie Speicher für den kopierten Wert zuzuweisen, und kopieren tatsächlich der Wert in den neu zugewiesenen Speicher. Und wenn Sie Speicher reservieren, müssen Sie natürlich auch frei haben.

Eine einfachere Lösung ist, Zeiger überhaupt nicht zu verwenden. Das Vermeiden von Zeigern ist normalerweise ein sehr guter Weg, um undefiniertes Verhalten und Abstürze im Allgemeinen zu vermeiden.