2010-12-09 9 views
2

Also habe ich eine Funktion, die eine Char ** - Variable mit einigen String-Daten lädt. Mein Ziel ist es, den Prozess zu verzweigen und einige dieser Daten im Kind und einige vom Elternteil zu drucken. Ich kann jedoch nicht auf den Zeiger nach dem Aufruf von fork() verweisen.Verweis auf Zeiger nach einem Aufruf von fork() in C

Ich dachte, dass fork() eine Kopie des gesamten Adressraum des übergeordneten Prozesses, der, dass es die verschiedenen Stapelzeiger würde ... scheint gemacht derzeit

Im Wesentlichen mein Code wie folgt aussieht:

load_data(char **data); 

char** data; 
load_data(data); 
printf("String 0: %s\n", data[0]); 
fork(); 
printf("String 0 again: %s\n", data[0]); /* Segfaults Here! */ 

Wer hat irgendwelche Ideen, was ich falsch mache? Ich habe ein bisschen Google suchen, und es scheint, dass was ich tue, sollte funktionieren - aber es tut nicht. So ich etwas Grundsätzliches bin Missverständnis ...

+0

* "Ich dachte, dass fork() habe eine Kopie des gesamten Adressraums des Elternprozesses erstellt, der so aussieht, als würde er die verschiedenen Stapelzeiger enthalten ... "* Dies ist nicht relevant für die Frage, aber zumindest auf den meisten modernen UNIX-Systemen," fork "doesn ' t Kopieren Sie den gesamten Adressraum zu dem Zeitpunkt, zu dem er ist namens. Es verwendet ein * Copy-on-Write * -Schema; Die Speicherseiten werden kopiert, sobald sie sich ändern. Es fühlt sich an wie die Speicherseiten, die zur Zeit von "fork" kopiert wurden. –

Antwort

3

Sie machen schlechte Zeigeroperationen und einfach Glück beim ersten Anruf bekommen - hier ist das, was der Code soll wie folgt aussehen:

load_data(char **data); 

char* data = NULL; 
load_data(&data); 
printf("String 0: %s\n", data); 
fork(); 
printf("String 0 again: %s\n", data); /* Doesn't Segfault Here! */ 
+1

Es sollte übrigens "NULL" in Großbuchstaben sein. –

+0

Dies setzt voraus, dass die Funktion des OP in C++ 'load_data (char * &)' wäre. Was es wahrscheinlich wäre, und die Verwendung des OP ist sicherlich falsch, aber es gibt eine Chance, dass das OP einen 'char **' braucht. –

+0

Ich brauche tatsächlich char **, da ich um etwas vorhandenen Code herumarbeite und die load_data-Funktion bereits für mich geschrieben wurde, indem ich den char ** nehme. In meinem tatsächlichen Anwendungsfall sind die Daten tatsächlich ein argv **, und ich werde den argv [0] an einen execve-Aufruf übergeben. Irgendwelche Tipps, um das in diesem Fall zu machen? – camperdave

1

In Ihrem Fall, data zeigt nirgendwo hin. Die Verwendung einer nicht initialisierten Variablen ist ein nicht definiertes Verhalten. Auch wenn es sich innerhalb der load_data-Funktion geändert hat, ist die Änderung außerhalb nicht sichtbar.

Sie müssen entweder data Punkt auf etwas gültig machen, oder übergeben Sie die Adresse data an die Funktion, um die Änderungen "zurückgeben", wie in load_data(char ***data).


Ihren Code, mit minimalen Änderungen es ein komplettes Programm zu machen, "Werke" für mich

#include <assert.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 

int load_data(char **data); 

int main(void) { 
    char **data; 
    data = malloc(2 * sizeof *data); 
    assert(data && "no memory"); 
    load_data(data); 
    printf("String 0: %s\n", data[0]); 
    fork(); 
    printf("String 0 again: %s\n", data[0]); 
    return 0; 
} 

int load_data(char **data) { 
    data[0] = "one"; 
    data[1] = "two"; 
    return 2; 
} 

und einen Probelauf

 
$ ./a.out 
String 0: one 
String 0 again: one 
String 0 again: one 
+0

Ihr Code funktioniert auch auf meinem System, aber ich kann in diesem Fall keinen dynamischen Speicher verwenden. Ich bin mir nicht sicher, was anders ist zwischen meinem eigentlichen Code und deinem anderen, als das ... was ein Teil davon ist, warum ich so verwirrt bin. – camperdave

+0

Ihre 'Daten' sind nicht initialisiert. Sehen Sie meine neuen Kommentare oben auf meiner Antwort. – pmg