2010-09-07 9 views
5

que estoy tratando de averiguar los tipos de archivos utilizando el código c, aquí está el códigopuntero char gratuito en c

char *get_file_type(char *path, char *filename) 
{ 
    FILE *fp; 
    char command[100]; 
    char file_details[100]; 
    char *filetype; 

    sprintf(command, "file -i %s%s", path, filename); 
    fp = popen(command, "r"); 
    if (fp == NULL) { 
     printf("Failed to run command\n"); 
     exit(1); 
    } 
    while (fgets(file_details, sizeof(file_details)-1, fp) != NULL) { 
     filetype = (strtok(strstr(file_details, " "), ";")); 
    } 

    pclose(fp); 
    return filetype; 
} 

aquí en lugar de declarar comando [], puedo utilizar * mando? Traté de usarlo, pero arrojó una excepción. no necesitamos liberar las variables declaradas como comando []? Si es así, ¿cómo?

Respuesta

5

Puede utilizar char *command;, pero luego, debe asignar una cierta memoria de command para referirse a con una llamada a malloc() y cuando haya terminado ITH que la memoria, tiene que ser liberado de nuevo con una llamada a free().

Como puede ver, eso es mucho más trabajo que usar una matriz de tamaño fijo (como lo hace ahora), pero también se puede hacer mucho más seguro, porque podría crear una memoria intermedia exactamente de la derecha tamaño, en lugar de esperar que la longitud total del comando no exceda los 100 caracteres.

Aparte de eso, el código tiene un problema: El puntero filetype que la función devuelve puntos a una ubicación dentro de la matriz file_details, pero esa matriz será limpiado por el compilador cuando se ejecuta la instrucción return, por lo que el puntero que devuelve la función se refiere a una memoria que está marcada como "libre para ser utilizada para otros fines".

Si no es un problema que el resultado de get_file_type sólo es válida para un archivo a la vez, se puede declarar la matriz como file_detailsstatic, por lo que será preservado a través de llamadas a la función.

+0

¿puedo usar strdup en su lugar? –

+0

Puede, pero debe recordar llamar 'libre' en la (s) función (es) de llamada para evitar una pérdida de memoria. –

1

¿Por qué lo cambiarías? Para los búferes temporales, las personas generalmente declaran las matrices con [] para que no tengan que preocuparse por la eliminación de basura.

+0

pero ¿me puede explicar cómo hacerlo? –

+0

Por un lado, probablemente tendría sentido asignar dinámicamente un búfer en función de las longitudes de 'ruta' y' nombre de archivo' en lugar de permitir silenciosamente un desbordamiento de búfer. (Sin embargo, las matrices de longitud variable C99 resolverían esto. Usar 'snprintf' en lugar de' sprintf' también sería aconsejable.) – jamesdlin

+4

Esto debería ser un comentario ... – zeboidlund

11

Cuando se declara una matriz:

char command[100]; 

el compilador asigna la memoria para ello (100 caracteres en este caso) y command apunta al comienzo de esa memoria. Puede acceder a la memoria que ha asignado:

command[0] = 'a'; // OK 
command[99] = 'A'; // OK 
command[100] = 'Z'; // Error: out of bounds 

pero no se puede cambiar el valor de command:

command = NULL;  // Compile-time error 

La memoria será liberado automáticamente cuando command sale del ámbito.


Cuando se declara un puntero:

char *commandptr; 

sólo se crea una única variable para señalar a char s, pero no apunta a nada todavía.Tratando de usarlo sin inicializar es un error:

commandptr[0] = 'A'; // Undefined behaviour; probably a segfault 

Es necesario asignar la memoria por sí mismo utilizando malloc:

commandptr = malloc(100); 
if (commandptr) { 
    // Always check that the return value of malloc() is not NULL 
    commandptr[0] = 'A'; // Now you can use the allocated memory 
} 

y liberarla cuando haya terminado con él:

free(commandptr); 
+0

En realidad, la matriz de pila no se libera, porque no es necesario. Para ser totalmente honesto, malloc y free son syscalls (bueno, wrappers para ellos), mientras que stack array no lo son. – KAction