Segfault en progtwig C, llamada malloc

Estoy escribiendo un progtwig que toma una lista de rutas (variable de entorno), divide las rutas y las imprime. Al comstackrlo me sale un segfault. Lo siguiente es mi salida en GDB:

Program received signal SIGSEGV, Segmentation fault. 0x0000000000400eb0 in dest (name=0x7fffffffbce0 "PATH") at executables.c:100 100 dest[i] = malloc(srclen+1); 

En valgrind:

 ==21574== 1 errors in context 2 of 3: ==21574== Use of uninitialised value of size 8 ==21574== at 0x400EB0: dest (executables.c:100) ==21574== by 0x400B5B: main (main.c:9) 

Esta es mi función:

 char** dest(char *name){ int i=0; char *vp; const char s[2]=":"; char *token; char **dest; name[strlen(name)-1]='\0'; vp=getenv(name); if(vp == NULL){ exit(1); } token =strtok(vp,s); while( token != NULL ){ size_t srclen = strlen(token); dest[i] = malloc(srclen+1); strcpy(dest[i], token); token = strtok(NULL, s); i++; } dest[i]=NULL; return dest; } 

Y este es mi principal:

 #include "executables.h" int main(int argc, char **argv){ char *path; char name[BUFSIZ]; printf("enter name of environment variable:\n"); fgets(name,BUFSIZ,stdin); char **p=dest(name); int j=0; while(p[j]!=NULL){ printf("%s\n",p[j]); j++; } return(0); } 

Utilice strdup () . Guarda pasos (también cuenta para ‘\ 0’). Debe asignar algo de memoria de antemano para el enfoque que está utilizando. De lo contrario, es posible que desee una lista vinculada y asignar paquetes en lugar de usar el patrón de matriz. Cuando dices dest[i] = estás indexando a un desplazamiento de memoria no asignada y almacenando algo allí, por lo que es un segvio.

 #include  #define MAXTOKENS 10000 char **get_dest(char *name) { // Since dest has to be exposed/persist beyond this function all // need dynamically allocate (malloc()) rather than stack allocate // of the form of: char *dest[MAXTOKENS]. char *dest = malloc(MAXTOKENS * sizeof (char *)); // <--- need to allocate storage for the pointers char *vp; if ((vp = getenv(name)) == NULL) exit(-1); // -1 is err exit on UNIX, 0 is success int i = 0; char *token = strtok(vp, ":"); while (token != NULL) { dest[i] = strdup(token); // <=== strdup() token = strtok(NULL, ":"); i++; } // dest[i] = NULL; // Why are you setting this to NULL after adding token? return dest; } 

Es mejor si main () se encarga de pasar una cadena apropiada terminada en nulo a la función get_dest () porque main es donde se manejan los fgets () meticulosos. En general, usted quiere hacer las cosas localmente donde tenga más sentido y sea más relevante. Si alguna vez tomaste tu función get_dest () y la usaste en algún lugar donde las cadenas no fueron leídas por fgets (), solo sería un paso perdido para sobrescribir el terminador allí. Entonces, al inicializar la matriz de caracteres a cero antes de fgets (), no tiene que preocuparse por establecer el byte final en '\ 0'.

Y, finalmente, probablemente no sea bueno que su nombre de función sea el mismo nombre que la variable que devuelve dest. En algunas situaciones, tener varios símbolos en su progtwig con el mismo nombre puede causarle problemas.

 #include "executables.h" int main(int argc, char **argv) { char *path; char name[BUFSIZ] = { 0 }; // You could initialize it to zero this way printf("enter name of environment variable:\n"); // bzero(name, BUFSIZ); //... or you could initialize it to zero this way then fgets(name, BUFSIZ, stdin); char **p = get_dest(name); int j = 0; while(p[j] != NULL) { printf("%s\n", p[j]); j++; free(p[j]); // like malloc(), strdup'd() strings must be free'd when done } free(p); return 0; } 
  dest[i] = malloc(srclen + 1); 

Debe asignar memoria para el puntero a los punteros char (dest), así como a cada puntero char almacenado en dest. En el código que proporcionó, no se toma ningún paso.

De la página de manual de getenv:

Notas … Como suele implementarse, getenv () devuelve un puntero a una cadena dentro de la lista de entornos. La persona que llama debe tener cuidado de no modificar esta cadena, ya que eso cambiaría el entorno del proceso.

Tu código viola esa regla:

 vp=getenv(name); ... token =strtok(vp,s); 

Esta es una operación de escritura de memoria ilegal.