Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: NOB2014 en 19 Junio 2016, 14:33 pm



Título: Concatenar cadenas con memoria dinámica en lenguaje C.
Publicado por: NOB2014 en 19 Junio 2016, 14:33 pm
Hola, gente.
Les quito un poco de tiempo porque si bien estoy leyendo que es lo que causa el doble free no logro solucionarlo por mí mismo y si lo lograra me quedarían dudas en la función concatenar, les digo esto porque si bien logre que no me diera error en la compilación lo hice a fuerza de prueba/error/solución pero no teniendo claro que es lo que estaba haciendo. -
Las cosas que no me quedan claras:

1): Porque debo hacer que la función se declare como un puntero a función.
2): Porque el error del doble free.
3): Como se hace para poner un espacio entre las dos frases (por programación, claro).-
  
Código
  1. #include <stdio.h>
  2. #include<string.h>
  3. #include<stdlib.h>
  4.  
  5. #define MAX 51
  6.  
  7. void ingreso( char origUno[], char origDos[] );
  8. void limpiarBuffer( char cadena[] );
  9. char *concatenar( char *origUno, char *origDos );
  10.  
  11. int main( void ){
  12. char origUno[MAX] = "", origDos[MAX] = "", *ptrConc = NULL;
  13.  
  14. ingreso( origUno, origDos );
  15. ptrConc = concatenar( origUno, origDos );
  16.  
  17. printf("\n %s", ptrConc);
  18.  
  19. free(ptrConc);
  20.  
  21. return 0;
  22. }
  23.  
  24. void ingreso( char origUno[], char origDos[] ){
  25.  
  26. printf( "\n Ingrese una frase(maximo %d caracteres)............:", MAX-1 );
  27. fgets(origUno, MAX, stdin);
  28. limpiarBuffer( origUno );
  29.  
  30. printf( "\n Ingrese frase a concatenar (maximo %d caracteres)..:", MAX-1 );
  31. fgets(origDos, MAX, stdin);
  32. limpiarBuffer( origDos );
  33. }
  34.  
  35. void limpiarBuffer( char cadena[] ){
  36. char *p = NULL;
  37. size_t ch;
  38.  
  39. if((p=strchr(cadena, '\n'))){
  40. *p='\0';
  41. }
  42. else{
  43. while((ch = getchar()) !='\n' && ch!=EOF);
  44. }
  45. }
  46.  
  47. char *concatenar( char *origUno, char *origDos ){
  48. size_t totCarac = strlen( origUno ) + strlen( origDos ) + 1;
  49. char *arr = ( char* )malloc( totCarac * sizeof(char) );
  50. arr = strcat( origUno, origDos );
  51.  
  52. return arr;
  53. }
  54.  

Saludos y desde ya muchas gracias. -


Título: Re: Doble free.
Publicado por: AlbertoBSD en 19 Junio 2016, 15:41 pm

1): Porque debo hacer que la función se declare como un puntero a función.


Es el tipo de dato que devuelve la funcion, no es que sea un puntero a funcion, es una funcion que devuelve un tipo de  dato
;
Código
  1. char* funcion();

No veo ningun doble free en tu codigo. Lo que veo es que estas tratando de liberar una sección de memoria no liberable. Esto es que solo puedes liberar memoria reservada por malloc, calloc y realloc pero tu apuntador posteiormente apunta a origUno por el strcat que haces incorrectamente.

Segun:

Código
  1. char *arr = ( char* )malloc( totCarac * sizeof(char) );

Reservas memoria el buffer completo pero despues reasignas el valor de arr a la direccio  de origUno.

Código
  1. arr = strcat( origUno, origDos );

que seria la direccion de origUno...

Necesitas primero realizar un strncpy de origUno a arr y luego realizar la concatenacion.

Sobre el espacio tendrias que hacer:

Código
  1. strcpy(arr,origUno);
  2. strcat( arr, " ");
  3. strcat( arr, origDos );


Nota que uso strcpy y no strncpy ya que como capturaste correctamente origUno y reservastes memoria suficiente para arr no hay riesgo de bufferoverflow. En cualquier otro caso usaria strncpy...

Saludos


Título: Re: Doble free.
Publicado por: NOB2014 en 19 Junio 2016, 19:11 pm
Hola, Alberto. -
Muchas gracias amigo funciona a la perfección, pero igual me queda una duda y es que al tener un espacio creado con:
Código
  1. strcat( arr, " ");
¿no debería reservar un espacio más?  
Código
  1. size_t totCarac = strlen( origUno ) + strlen( origDos ) + 1;
Un abrazo.


Título: Re: Doble free.
Publicado por: AlbertoBSD en 19 Junio 2016, 19:22 pm
Así es se me paso comentar eso.

Debería de ser +2 en lugar de +1.

Saludos.