elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Los 10 CVE más críticos (peligrosos) de 2020


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Problema al liberar memoria con free()
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Problema al liberar memoria con free()  (Leído 3,419 veces)
mester

Desconectado Desconectado

Mensajes: 219


https://www.youtube.com/watch?v=IlY9C6pzxKc


Ver Perfil WWW
Problema al liberar memoria con free()
« en: 21 Mayo 2016, 04:19 am »

Hola.
Estoy haciendo una shell y de momento va bien xd el problema surge cuando quiero liberar la variable que contiene los argumentos. Adjunto codigo:
Código
  1. char **GetCommand(int maxLength) { /*Recibe un comando*/
  2.  int argc, secArgc;
  3.  char *stdBuffer = (char *)malloc(sizeof(char) * maxLength);
  4.  char **stdCommand = (char **)malloc(sizeof(char *) * (maxLength / 2));
  5.  
  6.  argc = secArgc = 0;
  7.  stdCommand[argc] = (char *)malloc(sizeof(char) * (maxLength / 4));
  8.  
  9.  printf("%s ", COMMAND_PROMPT);
  10.  fgets(stdBuffer, maxLength, stdin);
  11.  stdBuffer[strlen(stdBuffer) - 1] = '\0';
  12.  
  13.  while(*stdBuffer) {
  14.    if(*stdBuffer == '\n') {
  15.      break;
  16.    }
  17.  
  18.    if(*stdBuffer == ' ') {
  19.      secArgc = 0;
  20.      stdCommand[++argc] = (char *)malloc(sizeof(char) * (maxLength / 4));
  21.    }
  22.  
  23.    stdCommand[argc][secArgc++] = *stdBuffer++;
  24.  }
  25.  stdBuffer = NULL;
  26.  free(stdBuffer);
  27.  
  28. return stdCommand;
  29. }

Con esta función se recibe un comando. Y este sería el main:
Código
  1. char **stdLine = NULL;
  2.  
  3.  while(stdLine = GetCommand(1024)) { /*Mientras se reciba un comando*/
  4.    printf("%s\n", stdLine[0]);
  5.  
  6.    switch(comExecute((const char **)stdLine)) {
  7.      case 0: break;
  8.      case 1: perror("Can\'t execute these command\n");
  9.      case EXIT_COMMAND: exit = 1;
  10.    }
  11.    if(exit) { /*Si ha escrito 'exit'*/
  12.      break;
  13.    }
  14.  
  15.    free(stdLine);
  16.  }

El problema surge con el free(stdLine); que a la hora de imprimirlo se ve que se llena de basura o algo así, porque cuando se ejecuta el printf del main me saca carácteres raros al final de cadena que impiden que sea bien leida. He pensado en poner stdLine = NULL; pero lo que quiero es liberar memoria. ¿Sería lo mismo poner free(stdLine) que stdLine = NULL? Yo creo que no, pero como no me dedico a la programación profesionalmente, sino más por afición, pues no tengo mucha idea.

Gracias de antemano.


En línea

Justicia es dar a cada uno lo que se merece
AlbertoBSD
Programador y
Moderador Global
***
Desconectado Desconectado

Mensajes: 3.696


🏴 Libertad!!!!!


Ver Perfil WWW
Re: Problema al liberar memoria con free()
« Respuesta #1 en: 21 Mayo 2016, 06:04 am »

trata de usar calloc en lugar de malloc malloc te da memoria no inicializada en 0 y calloc si lo hace.

Trata de siempre pedir un byte mas de lo que necesitas para dejar un byte nullo al final.

Asi quedaria
Código
  1.  char *stdBuffer = (char *)calloc(sizeof(char) * maxLength+1,1);
  2.  char **stdCommand = (char **)calloc(sizeof(char *) * (maxLength / 2)+1,1);

Veo que estas separando por cada espacio por que no usas strtok?

Un ejemplo seria el que mostre en el siguiente tema.

https://foro.elhacker.net/programacion_cc/mi_programa_crashea_al_usar_strtok-t452597.0.html

te dejo un video que he hecho para que veas la diferencia.



saludos


« Última modificación: 21 Mayo 2016, 06:14 am por AlbertoBSD » En línea

mester

Desconectado Desconectado

Mensajes: 219


https://www.youtube.com/watch?v=IlY9C6pzxKc


Ver Perfil WWW
Re: Problema al liberar memoria con free()
« Respuesta #2 en: 21 Mayo 2016, 10:54 am »

Veo que estas separando por cada espacio por que no usas strtok?

Porque prefiero usar funciones mías. Una cosa, es lo mismo si hago esto:
Código
  1. free(stdLine);
Que si hago esto:
Código
  1. for(i = 0; i < 10; i++) {
  2.  free(stdLine[i]);
  3. }
  4. free(stdLine);

Y otra cosa... ¿Como puedo saber si un puntero está apuntando a alguna direccion de memoria?
Porque por ejemplo puedo declararlo pero no inicializarlo, y despues al liberarlo me da una violacion de segmento.

Gracias.
En línea

Justicia es dar a cada uno lo que se merece
AlbertoBSD
Programador y
Moderador Global
***
Desconectado Desconectado

Mensajes: 3.696


🏴 Libertad!!!!!


Ver Perfil WWW
Re: Problema al liberar memoria con free()
« Respuesta #3 en: 21 Mayo 2016, 13:34 pm »

[
Porque prefiero usar funciones mías. Una cosa, es lo mismo si hago esto:


Y otra cosa... ¿Como puedo saber si un puntero está apuntando a alguna direccion de memoria?
Porque por ejemplo puedo declararlo pero no inicializarlo, y despues al liberarlo me da una violacion de segmento.

Gracias.


Yo tambien prefiero usar funciones propias para aprender los algoritmos y en general saber lo que esta haciendo el codigo.

Tienes que hacer una validaciones..

Código
  1. char *stdBuffer = NULL;   //Asignacion redundante pero ña agrego para fines didacticos...
  2. stdBuffer = calloc(maxLength+1,1);
  3. if(stdBuffer != NULL){
  4. //guardar cosas en stdBuffer
  5. ...
  6. free(stdBuffer);
  7. }
  8. else{
  9. //No se pudo inicializar error... muy raro pero puede pasar
  10. }
  11.  

Código
  1. for(i = 0; i < 10; i++) {
  2.  if(stdLine[i] != NULL){
  3.    free(stdLine[i]);
  4.    stdLine[i] = NULL;
  5.  }
  6. }
  7. if(stdLine != NULL){
  8.  free(stdLine);
  9.  stdLine = NULL;
  10. {
  11.  

Este es el correcto... tienes que liberar primero los apuntadores individuales y despues el doble apuntador.. y validar antes que no sean NULL.

ahora tambien ten cuidado de no liberar 2 veces un mismo apuntador ahi marcaria error..
« Última modificación: 21 Mayo 2016, 13:36 pm por AlbertoBSD » En línea

mester

Desconectado Desconectado

Mensajes: 219


https://www.youtube.com/watch?v=IlY9C6pzxKc


Ver Perfil WWW
Re: Problema al liberar memoria con free()
« Respuesta #4 en: 21 Mayo 2016, 13:41 pm »

Vale, ya me ha quedado claro, gracias por la ayuda, camarada.
En línea

Justicia es dar a cada uno lo que se merece
ivancea96


Desconectado Desconectado

Mensajes: 3.412


ASMático


Ver Perfil WWW
Re: Problema al liberar memoria con free()
« Respuesta #5 en: 21 Mayo 2016, 13:52 pm »

Código
  1. char **GetCommand(int maxLength) { /*Recibe un comando*/
  2. int argc, secArgc;
  3. char *stdBuffer = (char *)malloc(sizeof(char) * maxLength);
  4. char **stdCommand = (char **)malloc(sizeof(char *) * (maxLength / 2));
  5.  
  6. argc = secArgc = 0;
  7. stdCommand[argc] = (char *)malloc(sizeof(char) * (maxLength / 4));
  8.  
  9. fgets(stdBuffer, maxLength, stdin);
  10.  
  11. while(*stdBuffer) {
  12. if(*stdBuffer == '\n') {
  13. break;
  14. }
  15.  
  16. if(*stdBuffer == ' ') {
  17. stdCommand[argc][secArgc] = '\0';
  18. stdCommand[++argc] = (char *)malloc(sizeof(char) * (maxLength / 4));
  19. secArgc = 0;
  20. }else
  21. stdCommand[argc][secArgc++] = *stdBuffer;
  22. stdBuffer++;
  23. }
  24. stdCommand[argc][secArgc] = '\0';
  25. free(stdBuffer);
  26. stdBuffer = NULL;
  27.  
  28. return stdCommand;
  29. }

Lo ideal, es que vayas poniendo un '\0' al final de cada cadena.
Es interesante ver que no tienes forma de saber el numero de argumentos del comando. Tendrás que devolver tambien un entero.
En cuanto al código, reorganicé para 2 cosas:
-1: poner los '\0'
-2: no anexar el espacio a las cadenas. Para eso el 'else'.

Por lo demás, estaría bien que primero calculases la cantidad de argumentos que tiene la cadena, y luego hicieras los malloc. Sinó, tendrás un montón de memoria perdida.
En línea

mester

Desconectado Desconectado

Mensajes: 219


https://www.youtube.com/watch?v=IlY9C6pzxKc


Ver Perfil WWW
Re: Problema al liberar memoria con free()
« Respuesta #6 en: 21 Mayo 2016, 14:04 pm »

En cuanto al código, reorganicé para 2 cosas:
-1: poner los '\0'
-2: no anexar el espacio a las cadenas. Para eso el 'else'.

Por lo demás, estaría bien que primero calculases la cantidad de argumentos que tiene la cadena, y luego hicieras los malloc. Sinó, tendrás un montón de memoria perdida.
siii, eso ya lo tenía puesto en el codigo, es que este no lo he actualizado. A ver que te parece este:
Código
  1. char **GetCommand(int maxLength, int *numArgs, int *background) { /*Recibe un comando*/
  2.  int argc, secArgc;
  3.  char *stdBuffer = (char *)calloc(sizeof(char) * maxLength, sizeof(char) + 1);
  4.  char **stdCommand = (char **)calloc(sizeof(char *) * (maxLength / 2) + 1, sizeof(char));
  5.  
  6.  argc = secArgc = *background = 0;
  7.  stdCommand[argc] = (char *)calloc(sizeof(char) * (maxLength / 6), sizeof(char));
  8.  
  9.  printf("%s ", COMMAND_PROMPT);
  10.  fgets(stdBuffer, maxLength, stdin);
  11.  stdBuffer[strlen(stdBuffer) - 1] = '\0';
  12.  
  13.  if(!seastr("&", stdBuffer)) {
  14.    *background = 1;
  15.  }
  16.  
  17.  while(*stdBuffer) {
  18.    if(*stdBuffer == '\n') {
  19.      break;
  20.    }
  21.  
  22.    if(*stdBuffer == ' ') {
  23.      *stdBuffer++;
  24.      if(*stdBuffer != '&') {
  25.        stdBuffer[++secArgc] = '\0';
  26.        secArgc = 0;
  27.        stdCommand[++argc] = (char *)calloc(sizeof(char) * (maxLength / 4), sizeof(char));
  28.      }
  29.    }
  30.    else {
  31.      stdCommand[argc][secArgc++] = *stdBuffer++;
  32.    }
  33.  }
  34.  *numArgs = argc;
  35.  
  36.  stdCommand[++argc] = NULL;
  37.  stdBuffer = NULL;
  38.  free(stdBuffer);
  39.  
  40. return stdCommand;
  41. }

Pongo lo del & porque al ser una shell, el & indica que el proceso será ejecutado en background y tal. Y en cuanto a la funcion seastr() es una funcion propia que busca en una cadena y devuelve ciertos valores:
Código
  1. int seastr(const char *str1 /*word*/,
  2.            const char *str2 /*string*/) {
  3. /*Returns 0 if str1 is in str2*/
  4.  if(str1 == NULL||str2 == NULL) {
  5.    return 1;
  6.  }
  7.  
  8.  char *cp = (char *)str2;
  9.  char *sr, *fr;
  10.  
  11.  while(*cp) {
  12.    sr = cp;
  13.    fr = (char *)str1;
  14.    while(*sr && *fr && (*sr == *fr)) {
  15.      sr++, fr++;
  16.    }
  17.    if(!*fr) {
  18.      return 0;
  19.    }
  20.    cp++;
  21.  }
  22. return 1;
  23. }

Si ves algo que se podría mejorar de ahí, por favor, dimelo. Gracias.
« Última modificación: 21 Mayo 2016, 14:06 pm por mester » En línea

Justicia es dar a cada uno lo que se merece
AlbertoBSD
Programador y
Moderador Global
***
Desconectado Desconectado

Mensajes: 3.696


🏴 Libertad!!!!!


Ver Perfil WWW
Re: Problema al liberar memoria con free()
« Respuesta #7 en: 21 Mayo 2016, 14:35 pm »

Todo bien  ;-) ;-) ;-)

Solo como comentario...

Código
  1.  char *stdBuffer = (char *)calloc(maxLength+ 1, sizeof(char));
  2.  char **stdCommand = (char **)calloc( (maxLength / 2) + 1, sizeof(char*));

el sizeof(char) en el primer parametro esta sobrado por que se especifica en el segundo parametro...

Ahora el segundo calloc estas reservando memoria para X cantidad de apuntadores entonces el sizeog(char) le falta el *  dentro del parentesis para que te reserve elementos del damañao de un apuntador usualemnte son elementos de 4 u 8 bytes..

Sobre la variable maxLength no estoy seguro de cuanto valga pero si alguien mete mas comandos que maxLength  puede hacer tu app vulnerable a buffer overflow....

Pero solo es una observacion para alguien que esta aprendiendo por hobby te tengo que decir que dominas el lenguaje con cierta maestria...

Saludos!
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
liberar memoria ram?
Windows
nova.to 1 3,628 Último mensaje 20 Abril 2011, 16:40 pm
por el-brujo
Problema para liberar memoria - C
Programación C/C++
HRSLASH 6 3,571 Último mensaje 19 Abril 2012, 14:26 pm
por Eternal Idol
Liberar memoria
Programación C/C++
Upeksa 3 2,259 Último mensaje 17 Septiembre 2013, 19:23 pm
por Upeksa
MEMORIA SIN LIBERAR C++
Programación C/C++
guero 6 3,029 Último mensaje 7 Julio 2020, 14:41 pm
por Meta
Saber la memoria liberada con free() ?
Programación C/C++
Locura_23 2 3,270 Último mensaje 1 Julio 2021, 01:46 am
por Locura_23
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines