Programación en C

malloc en lenguaje c

malloc en lenguaje c
Puedes venir aquí por dos razones: o quieres asignar contenido dinámicamente o quieres saber más sobre cómo funciona malloc. En cualquier caso, estás en el lugar correcto! La asignación dinámica es un proceso que ocurre mucho, pero generalmente no lo usamos nosotros mismos: la gran mayoría de los lenguajes de programación administran la memoria por usted, ya que es un trabajo difícil y si no lo hace correctamente, hay implicaciones de seguridad.

Sin embargo, si está haciendo C, C ++ o código ensamblador, o si implementa un nuevo módulo externo en su lenguaje de programación favorito, necesitará administrar su asignación de memoria dinámica usted mismo.

¿Qué es la asignación dinámica?? Por que necesito malloc?

Bueno, en todas las aplicaciones, cuando creas una nueva variable - a menudo se llama declarar una variable - necesitas memoria para almacenarlo. Como su computadora está en los días modernos, puede ejecutar más de una aplicación a la vez y, por lo tanto, cada aplicación debe informarle a su sistema operativo (aquí Linux) que necesita esa cantidad de memoria. Cuando escribe este tipo de código:

#incluir
#incluir
#define DISK_SPACE_ARRAY_LENGTH 7
void getFreeDiskSpace (int statsList [], size_t listLength)
regreso;

int main ()
/ * Contiene el espacio libre en disco de los últimos 7 días. * /
int freeDiskSpace [DISK_SPACE_ARRAY_LENGTH] = 0;
getFreeDiskSpace (freeDiskSpace, DISK_SPACE_ARRAY_LENGTH);
return EXIT_SUCCESS;

La matriz freeDiskSpace necesita memoria, por lo que deberá solicitar la aprobación de Linux para obtener algo de memoria. Sin embargo, como es obvio al leer el código fuente que necesitará una matriz de 7 int, el compilador automáticamente lo solicita a Linux y lo asignará a la pila. Esto básicamente significa que este almacenamiento se destruye cuando devuelve la función donde se declara la variable. Por eso no puedes hacer eso:

#incluir
#incluir
#define DISK_SPACE_ARRAY_LENGTH 7
int * getFreeDiskSpace ()
int statsList [DISK_SPACE_ARRAY_LENGTH] = 0;
/* POR QUÉ ESTAMOS HACIENDO ESO?! statsList será DESTRUIDA! * /
return statsList;

int main ()
/ * Contiene el espacio libre en disco de los últimos 7 días. * /
int * freeDiskSpace = NULL;
freeDiskSpace = getFreeDiskSpace ();
return EXIT_SUCCESS;

Ves más fácilmente el problema ahora? Entonces, quieres concatenar dos cadenas. En Python y JavaScript, haría:

newStr = str1 + str2

Pero como sabes, en C no funciona así. Entonces, para crear una URL, por ejemplo, debe concatenar dos cadenas, como la ruta de la URL y el nombre de dominio. En C, tenemos strcat, correcto, pero solo funciona si tiene una matriz con suficiente espacio para ello.

Te sentirás tentado a saber la longitud de la nueva cadena usando strlen, y estarías en lo cierto. Pero entonces, ¿cómo le pediría a Linux que reserve esta cantidad desconocida de memoria?? El compilador no puede ayudarlo: el espacio exacto que desea asignar solo se conoce en tiempo de ejecución. Ahí es exactamente donde necesita la asignación dinámica y malloc.

Escribiendo mi primera función C usando malloc

Antes de escribir código, una pequeña explicación: malloc le permite asignar un número específico de bytes para el uso de su aplicación. Es realmente simple de usar: llama a malloc con la cantidad de bytes que necesita y devuelve un puntero a su nueva área que Linux reservó para usted.

Solo tienes 3 responsabilidades:

  1. Compruebe si malloc devuelve NULL. Eso sucede cuando Linux no tiene suficiente memoria para proporcionar.
  2. Libera tus variables una vez que no las uses. De lo contrario, desperdiciará memoria y ralentizará su aplicación.
  3. Nunca use la zona de memoria después de haber liberado la variable.

Si sigues todas estas reglas, todo irá bien y la asignación dinámica te resolverá muchos problemas. Debido a que elige cuándo libera la memoria, también puede devolver de forma segura una variable asignada con malloc. Solo, no olvides liberarlo!

Si se pregunta cómo liberar una variable, es con la función gratuita. Llámelo con el mismo puntero que malloc le devolvió, y la memoria se libera.

Déjame mostrarte con el ejemplo de concat:

#incluir
#incluir
#incluir
/ *
* Al llamar a esta función, no olvide comprobar si el valor devuelto es NULL
* Si no es NULL, debe llamar a free en el puntero devuelto una vez que el valor
* ya no se usa.
* /
char * getUrl (const char * const baseUrl, const char * const toolPath)
size_t finalUrlLen = 0;
char * finalUrl = NULL;
/* Verificación de seguridad. * /
if (baseUrl == NULL || toolPath == NULL)
return NULL;

finalUrlLen = strlen (baseUrl) + strlen (toolPath);
/ * No olvides el '\ 0', de ahí el + 1. * /
finalUrl = malloc (tamaño de (char) * (finalUrlLen + 1));
/ * Siguiendo las reglas de malloc… * /
if (finalUrl == NULL)
return NULL;

strcpy (finalUrl, baseUrl);
strcat (finalUrl, toolPath);
return finalUrl;

int main ()
char * googleImages = NULL;
googleImages = getUrl ("https: // www.Google.com "," / imghp ");
if (googleImages == NULL)
return EXIT_FAILURE;

put ("URL de la herramienta:");
pone (googleImages);
/ * Ya no es necesario, libéralo. * /
gratis (googleImages);
googleImages = NULL;
return EXIT_SUCCESS;

Entonces ve un ejemplo práctico para usar asignaciones dinámicas. Primero, evito trampas como dar el valor de retorno de getUrl directamente a la función de venta. Luego, también me tomo el tiempo para comentar y documentar el hecho de que el valor de retorno debe liberarse correctamente. También verifico valores NULL en todas partes para que cualquier cosa inesperada se pueda detectar de manera segura en lugar de bloquear la aplicación.

Finalmente, tomo el cuidado especial de liberar la variable y luego establecer el puntero en NULL. Eso evita la tentación de usar, incluso por error, la zona de memoria ahora liberada. Pero como puede ver, es fácil liberar una variable.

Puede notar que usé sizeof en malloc. Permite saber cuántos bytes utiliza un carácter y aclara la intención en el código para que sea más legible. Para char, sizeof (char) siempre es igual a 1, pero si usa una matriz de int en su lugar, funciona exactamente de la misma manera. Por ejemplo, si necesita reservar 45 int, simplemente haga:

fileSizeList = malloc (tamaño de (int) * 45);

De esta manera, ves rápidamente cuánto quieres asignar, por eso siempre recomiendo su uso.

Cómo funciona malloc bajo el capó?

malloc y free son, de hecho, funciones incluidas en todos los programas C que se comunicarán con Linux en su nombre. También facilitará la asignación dinámica porque, al principio, Linux no le permite asignar variables de todos los tamaños.

Linux proporciona dos formas de obtener más memoria de hecho: sbrk y mmap. Ambos tienen limitaciones, y una de ellas es: puede asignar solo cantidades relativamente grandes, como 4096 bytes u 8.192 bytes. No puede solicitar 50 bytes como hice en el ejemplo, pero tampoco puede solicitar 5,894 bytes.

Esto tiene una explicación: Linux necesita mantener una tabla donde indique qué aplicación ha reservado qué zona de memoria. Y esta tabla también usa espacio, por lo que si cada byte necesitara una nueva fila en esta tabla, se necesitaría una gran parte de la memoria. Es por eso que la memoria se divide en grandes bloques de, por ejemplo, 4096 bytes, y al igual que no se pueden comprar 2 naranjas y media en un supermercado, no se pueden pedir medios bloques.

Entonces, malloc tomará estos bloques grandes y le dará una pequeña porción de estos bloques de memoria cada vez que lo llame. Además, si liberó algunas variables, pero no lo suficiente como para justificar la liberación de un bloque completo, el sistema malloc puede mantener bloques y reciclar zonas de memoria cuando vuelva a llamar a malloc. Esto tiene el beneficio de hacer que malloc sea más rápido, sin embargo, la memoria reservada por malloc no se puede usar en ninguna otra aplicación, mientras que el programa no la está usando actualmente en la realidad.

Pero malloc es inteligente: si llama a malloc para asignar 16 MiB o una gran cantidad, malloc probablemente le pedirá a Linux bloques completos dedicados solo para esta gran variable usando mmap. De esta manera, cuando llame gratis, es más probable que evite ese desperdicio de espacio. No se preocupe, malloc está haciendo un mejor trabajo en el reciclaje que los humanos con nuestra basura!

Conclusión

Creo que ahora es mejor que entiendas cómo funciona todo eso. Por supuesto, la asignación dinámica es un gran tema y creo que podemos escribir un libro completo sobre el tema, pero este artículo debería hacer que se sienta cómodo con el concepto tanto en general como con los consejos prácticos de programación.

Cómo desarrollar un juego en Linux
Hace una década, no muchos usuarios de Linux predecían que su sistema operativo favorito algún día sería una plataforma de juegos popular para videoju...
Puertos de código abierto de motores de juegos comerciales
Las recreaciones gratuitas, de código abierto y de motores de juegos multiplataforma se pueden usar para jugar títulos de juegos antiguos y también al...
Los mejores juegos de línea de comandos para Linux
La línea de comandos no es solo su mayor aliado cuando usa Linux, también puede ser la fuente de entretenimiento porque puede usarla para jugar muchos...