Leer un string con memoria dinámica ?

Iniciado por Locura_23, 17 Julio 2021, 20:16 PM

0 Miembros y 1 Visitante están viendo este tema.

Locura_23

Buenas genios, me surgió la siguiente duda, tal vez alguien que la tenga más clara puede ayudarme.

Es válida esta forma de asignar un string de manera dinámica ? Si o si necesito utilizar un arreglo estático auxiliar ?



#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
   char cadena_aux[100] = { 0 };
   char *cadena = NULL;
   int tam_cadena = 0;

   puts("Introducir una linea de texto.");
   fgets(cadena_aux,100,stdin);

   tam_cadena = strlen(cadena_aux);

   cadena = (char * ) malloc ( ( tam_cadena + 1 ) * sizeof(char) );

   if(cadena == NULL)
   {
       printf("Error en asignacion de memoria.\n");
       exit(EXIT_FAILURE);
   }

   strcpy(cadena,cadena_aux);

   printf("cadena = %s\n",cadena);

   free(cadena);

   return 0;
}




Luego, tras hacer la copia del estatico al dinámico, al intentar liberar la memoria utilizada en el arreglo estático me tira error...

WHK

#1
Hola,

Citarcadena = (char * ) malloc ( ( tam_cadena + 1 ) * sizeof(char) );

Te recomendaría reemplazar malloc por calloc para rellenar el espacio asignado con ceros ya que por defecto malloc asigna espacio pero no limpia, este espacio asignado puede contener partes de la memoria sin usar. Recuerda que strcpy realiza una copia byte por byte pero cadena es un stream no un array de datos, en ese caso deberías llamar a una función de copiado de memoria y no de caracteres, pero tu auxiliar no es un stream sino un array.

Si usas c++ en ves de c puro, podrías considerar utilizar std::string y std::getline para la obtención y procesamiento de datos en ves de tener que utilizar arrays de bytes de manera manual con riesgos de seguridad:

Código (cpp) [Seleccionar]

#include <iostream>
#include <string>

int main () {
 std::string cadena;

 std::cout << "Introducir una linea de texto: ";
 std::getline (std::cin, cadena);
 std::cout << "cadena = " << cadena << std::endl;

 return 0;
}


Saludos.

MAFUS

C separa la memoria en diferentes secciones para un programa. Está la pila (stack), el montón (heap), variables locales y estáticas, sólo lectura y memoria de programa. Las variables locales y los arrays (dentro de las funciones) van a la stack y de eso se encarga C de adquirir y liberar la memoria.
De hecho una vez compilado las variables de este tipo no existen: todo son operaciones con aritmética de punteros sobre el registro Base Pointer y por eso no se puede liberar memoria con free.

La que sí debes liberar es la memoria dinámica, que se guarda en el montón (heap). Lo único que hace allí C es adquirir tantos bytes como le has pedido, además de una cierta metainformación, y guarda en una tabla interna todo esto y te devuelve la dirección de memoria del inicio de memoria. Lo único que hará es mantener desde el inicio tantos bytes como lo has solicitado para que otra petición de memoria del montón no la pise. C no quiere saber nada más: si la pierdes, si la sobreescribes, lo que sea, C va a mantener esa memoria como 'ocupada' hasta que la liberes. Y por eso la memoria del montón sí debe ser liberada: le debes decir a C que elimine esa entrada de la tabla porque él no sabe, ni le importa, qué estás haciendo con ella.

Locura_23

@WHK , @MAFUS

muchas gracias por sus respuestas  :)

Entiendo que entonces no es posible liberar esa memoria ocupada por el arreglo estático auxiliar...? Me llama la atención porque aunque se quiera hacer que el usuario introduzca una cadena de cuantos caracteres quiera, al final habria un limite del estático...

MAFUS

No la liberas a mano. De esa se encarga C. Por eso si intentas liberar con free te saltará el error. Y no, la memoria puedes hacer una cadena tan larga como quieras. En los sistemas modernos el propio sistema no te dejará porque impide que los programas escriban o lean en direcciones de memoria que no están autorizados. En sistemas sin protección podrías escribir una cadena tan larga que podría sobreescribir cualquier parte de la memoria, y eso eran los ataques de buffer overflow.

Locura_23

Cita de: MAFUS en 19 Julio 2021, 00:41 AM
No la liberas a mano. De esa se encarga C. Por eso si intentas liberar con free te saltará el error. Y no, la memoria puedes hacer una cadena tan larga como quieras. En los sistemas modernos el propio sistema no te dejará porque impide que los programas escriban o lean en direcciones de memoria que no están autorizados. En sistemas sin protección podrías escribir una cadena tan larga que podría sobreescribir cualquier parte de la memoria, y eso eran los ataques de buffer overflow.

Comprendo, quedo clarisimo.  Gracias viejo!