Menú
Está libre
registro
hogar  /  Firmware/ Arrays. Asignación de memoria en C (función malloc) Errores típicos al usar

Matrices. Asignación de memoria en C (función malloc) Errores típicos al usar

Asignación de memoria dinámica

Principales problemas de aplicación

Puntero nulo

Un puntero nulo es un puntero que almacena significado especial se utiliza para indicar que una variable de puntero dada no hace referencia (apunta) a ningún objeto. Está representado por diferentes constantes en diferentes lenguajes de programación.

C # y Java: nulo

· En lenguajes C y C ++: macro 0 o NULL. Además, el estándar C ++ 11 propone uno nuevo para denotar un puntero nulo palabra clave nullptr

En lenguajes Pascal y Ruby: nulo

Componente Pascal: NIL

En Python: Ninguno

Los punteros son difíciles de manejar. Es bastante fácil escribir un valor incorrecto en el puntero, lo que puede provocar un error difícil de reproducir. Por ejemplo, accidentalmente cambió la dirección de un puntero en la memoria, o asignó memoria incorrectamente para la información, y luego puede esperarlo una sorpresa: se sobrescribirá otra variable muy importante que se usa solo dentro del programa. En este caso, le resultará difícil reproducir el error. No será fácil comprender exactamente dónde está el error. Y no siempre será trivial eliminarlo (a veces hay que reescribir una parte importante del programa).

Para solucionar algunos de los problemas, existen métodos de protección y seguro:

Habiendo estudiado los punteros en el lenguaje C, descubrimos las posibilidades de la asignación dinámica de memoria. ¿Qué significa? Esto significa que con la asignación de memoria dinámica, la memoria no se reserva en la etapa de compilación, sino en la etapa de ejecución del programa. Y esto nos da la capacidad de asignar memoria de manera más eficiente, principalmente para arreglos. Con la asignación de memoria dinámica, no necesitamos establecer el tamaño de la matriz de antemano, especialmente porque no siempre se sabe qué tamaño debería tener la matriz. A continuación, veamos cómo puede asignar memoria.

La función Malloc () se define en archivo de cabecera stdlib.h, se usa para inicializar punteros con la cantidad de memoria requerida. La memoria se asigna desde el sector memoria de acceso aleatorio disponible para cualquier programa que se ejecute en esta máquina. El argumento de la función malloc () es el número de bytes de memoria que se asignarán, la función devuelve: un puntero al bloque asignado en la memoria. La función malloc () funciona como cualquier otra función, nada nuevo.

Porque Varios tipos los datos tienen diferentes requisitos de memoria, de alguna manera tenemos que aprender cómo obtener el tamaño en bytes para los datos diferentes tipos... Por ejemplo, necesitamos un pedazo de memoria para una matriz de valores int; este es un tamaño de memoria, y si necesitamos asignar memoria para una matriz del mismo tamaño, pero que ya es de tipo char, esto es diferente. Talla. Por lo tanto, debe calcular de alguna manera el tamaño de la memoria. Esto se puede hacer con la operación sizeof (), que toma una expresión y devuelve su tamaño. Por ejemplo, sizeof (int) devolverá el número de bytes necesarios para almacenar un int. Consideremos un ejemplo:


Yandex.Direct


#incluir int * ptrVar = malloc (tamaño de (int));

En este ejemplo, en línea 3 al puntero ptrVar se le asigna una dirección a una ubicación de memoria, cuyo tamaño corresponde al tipo de datos int. Automáticamente, esta área de la memoria se vuelve inaccesible para otros programas. Esto significa que una vez que la memoria asignada se vuelve innecesaria, debe liberarse explícitamente. Si la memoria no se libera explícitamente, luego de que finalice el programa, la memoria no se liberará por sistema operativo, esto se denomina pérdida de memoria. También puede determinar el tamaño de la memoria asignada que se asignará pasando un puntero nulo, aquí hay un ejemplo:



Como puede ver, en tal registro hay una muy punto fuerte, no deberíamos llamar a la función malloc () usando sizeof (float). En su lugar, pasamos un puntero al tipo flotante a malloc (), en cuyo caso el tamaño de la memoria asignada se determinará automáticamente por sí mismo.

Esto es especialmente útil si necesita asignar memoria lejos de la definición del puntero:


float * ptrVar; / *. ... ... cien líneas de código * /. ... ... ptrVar = malloc (tamaño de (* ptrVar));

Si utilizó la construcción de la asignación de memoria con la operación sizeof (), entonces tendría que encontrar la definición de un puntero en el código, mirar su tipo de datos y solo entonces podría asignar la memoria correctamente.


#incluir void * malloc (tamaño_t tamaño);

Descripción


Devuelve un puntero al primer byte del área de memoria que se asignó desde el montón


La función malloc () devuelve un puntero al primer byte del área de memoria de tamaño que se asignó desde el montón. Si no hay suficiente memoria para satisfacer la solicitud, se devuelve un puntero nulo. Es importante asegurarse siempre de que el valor de retorno no sea un puntero nulo. Intentar usar un puntero nulo generalmente resulta en una falla completa del sistema.

Si está escribiendo programas de 16 bits para la familia de procesadores 8086 (como 80486 o Pentium), probablemente su compilador proporcione funciones adicionales asignaciones de memoria que tienen en cuenta el modelo de memoria segmentada que utilizan estos procesadores cuando operan en modo de 16 bits. Por ejemplo, estas pueden ser funciones que asignan memoria en el montón FAR (que está fuera del segmento de datos estándar). Estas funciones pueden asignar punteros a la memoria que es más grande que un segmento y liberar esa memoria.

Cada vez que se inicializaba el puntero, se usaba la dirección de una variable. Esto se debió al hecho de que el compilador de C ++ asigna automáticamente memoria para almacenar variables y, utilizando un puntero, puede trabajar con esta área asignada sin consecuencias. Sin embargo, existen funciones malloc () y free () que le permiten asignar y liberar memoria según sea necesario. Estas funciones se encuentran en la biblioteca y tienen la siguiente sintaxis:

void * malloc (tamaño_t); // función de asignación de memoria
void free (void * memblock); // función para liberar memoria

Aquí size_t es el tamaño del área de memoria asignada en bytes; void * es un tipo de puntero genérico, es decir no vinculado a ningún tipo en particular. Consideremos el funcionamiento de estas funciones usando el ejemplo de asignación de memoria para 10 elementos del tipo doble.

Listado 4.3. Programación dinámica de matrices.

#incluir
#incluir
int main ()
{
doble * ptd;
ptd = (doble *) malloc (10 * tamaño de (doble));
si (ptd! = NULL)
{
para (int i = 0; i ptd [i] = i;
) else printf ("No se pudo asignar memoria");
libre (ptd);
return 0;
}

Cuando se llama a la función malloc (), el área de memoria requerida se calcula para almacenar 10 elementos del tipo doble. Para hacer esto, use la función sizeof (), que devuelve el número de bytes necesarios para almacenar un elemento de tipo double. Luego, su valor se multiplica por 10 y el resultado es el volumen de 10 elementos del tipo doble. En los casos en los que, por alguna razón, no es posible asignar la cantidad de memoria especificada, la función malloc () devuelve NULL. Esta constante está definida en varias bibliotecas, incluidas y. Si la función malloc () devolvió un puntero al área de memoria asignada, es decir, no es igual a NULL, entonces se ejecuta un ciclo, donde se escriben los valores para cada elemento. Cuando el programa sale, llama función libre(), que libera memoria previamente asignada. Formalmente, un programa escrito en C ++, una vez completado, libera automáticamente toda la memoria asignada previamente y la función free (), en este caso, puede omitirse. Sin embargo, al compilar más programas complejos a menudo tiene que asignar y desasignar memoria muchas veces. En este caso, la función free () juega un papel importante, ya que la memoria no liberada no se puede reutilizar, lo que resultará en un desperdicio innecesario de recursos informáticos.

El uso de punteros se heredó del lenguaje C. Para simplificar el proceso de cambio de parámetros en C ++, se introduce un concepto como referencia. Un enlace es un alias (o segundo nombre) que los programas pueden usar para referirse a una variable. Para declarar un enlace, el programa usa el signo & delante de su nombre. La peculiaridad de utilizar enlaces es la necesidad de inicializarlos inmediatamente cuando se declaran, por ejemplo:

int var;
int & var2 = var;

Aquí se declara un enlace llamado var2, que se inicializa con la variable var. Esto significa que la variable var tiene su propio alias var2, a través del cual es posible cualquier cambio en los valores de la variable var. La ventaja de usar referencias sobre punteros es que deben inicializarse, por lo que el programador siempre está seguro de que la variable var2 funciona con un área de memoria asignada, y no con una arbitraria, lo cual es posible cuando se usan punteros. A diferencia de los punteros, un enlace se inicializa solo una vez, cuando se declara. La reinicialización dará como resultado un error en tiempo de compilación. Esto asegura la confiabilidad del uso de enlaces, pero reduce la flexibilidad de su uso. Normalmente, las referencias se utilizan como argumentos a funciones para modificar variables pasadas dentro de funciones. El siguiente ejemplo demuestra el uso de dicha función:

Listado 4.4. Un ejemplo de uso de enlaces.

intercambio vacío (int & a, int & b)
{
int temp = a;
a = b;
b = temp;
}
int main ()
{
int agr1 = 10, arg2 = 5;
intercambio (arg1, arg2);
return 0;
}

En este ejemplo, la función swap () toma dos argumentos, que son referencias a dos variables. Usando los nombres de referencia ayb, manipula las variables arg1 y arg2 definidas en la función principal main () y pasa como parámetros a la función swap (). La ventaja de la función swap () (que usa referencias en lugar de punteros a variables) es garantizar que la función toma los tipos de variables apropiados como argumentos, y no cualquier otra información, y que las referencias se inicializan correctamente antes de usarlas. El compilador realiza un seguimiento de esto al convertir el texto del programa a código de objeto y se muestra un mensaje de error si el uso de enlaces es incorrecto. A diferencia de los punteros con enlaces, no puede realizar las siguientes operaciones:

No puede obtener la dirección de un enlace utilizando el operador de dirección C ++;
no puede asignar un puntero a un enlace;
no puede comparar valores de referencia utilizando operadores de comparación de C ++;
no puede realizar operaciones aritméticas en un enlace, por ejemplo, agregar un desplazamiento;

Descripción de funciones

#incluir void * malloc (tamaño_t tamaño); void * calloc (tamaño_t num, tamaño_t tamaño);

Cita

malloc toma como argumento el tamaño del área asignada en bytes; devuelve un puntero sin tipo (void *) a un área de memoria del tamaño declarado, o NULL si es imposible asignar memoria. El contenido del área de memoria asignada no está definido.

calloc toma como argumento el número de elementos y el tamaño de cada elemento en bytes; devuelve un puntero sin tipo (void *) a un área de memoria del tamaño declarado, o NULL si es imposible asignar memoria. Los valores de los elementos se establecen en cero. malloc funciona más rápido que calloc, debido a la falta de una función para poner a cero la memoria asignada.

Parámetros de función

malloc

  • Talla- el tamaño del área de memoria asignada

calloc

  • num- el número de elementos distribuidos
  • Talla- el tamaño de cada elemento

Valor devuelto

Las funciones devuelven un puntero sin tipo (vacío *) al área de memoria en caso de éxito, o NULL en caso contrario.

Errores típicos al usar

  • La memoria permanece "ocupada" incluso si ningún puntero en el programa se refiere a ella (la función free () se usa para liberar memoria). La acumulación de partes "perdidas" de la memoria conduce a una degradación gradual del sistema. Los errores asociados con no liberar áreas de memoria ocupadas se denominan pérdidas de memoria. pérdidas de memoria).
  • Si la cantidad de datos que se procesan es mayor que la cantidad de memoria asignada, otras áreas del montón pueden resultar dañadas. Estos errores se denominan errores de desbordamiento del búfer. desbordamiento de búfer).
  • Si el puntero al área de memoria asignada continúa utilizándose después de la liberación, puede ocurrir una excepción al acceder a un bloque "que ya no existe" de memoria dinámica. excepción), un bloqueo del programa, otros datos dañados o nada (según el tipo de sistema operativo y el hardware utilizado).
  • Si para un área de memoria se llama a free () más de una vez, esto puede dañar los datos de la propia biblioteca que contiene malloc / free y provocar un comportamiento impredecible en momentos arbitrarios.
  • Organización fallida del programa, en la que se asignan y liberan una gran cantidad de pequeñas cantidades de memoria: es posible la fragmentación de la memoria libre ("línea de puntos"), en la que hay mucha memoria libre en total, pero es imposible asignar una gran parte.

El comportamiento exacto de las funciones se describe en el estándar ANSI C y se hace referencia en la definición de función en el estándar POSIX.

Ejemplos de uso

malloc

Float * matriz_dinámica = malloc (número_de_elementos * tamaño de (flotante)); si (! matriz_dinámica) ()

calloc

Float * matriz_dinámica = calloc (número_de_elementos, tamaño de (flotante)); si (! matriz_dinámica) ( / * manejar error de asignación de memoria * / } / * ... trabajando con elementos de matriz ... * / libre (matriz_dinámica); matriz_dinámica = NULL;

ver también

  • stdlib
  • alloca
  • jabón malloc
  • el jabón destruye

Fuentes de

  • malloc - Descripción de la función malloc en Estándar POSIX.
  • calloc - Descripción de la función calloc en el estándar POSIX.

Fundación Wikimedia. 2010.

Vea qué es "Malloc" en otros diccionarios:

    Malloc- est en informatique une fonction de la bibliothèque standard du C permettant d allouer dynamiquement de la mémoire. La libération de la mémoire ainsi réservée s effectue avec la fonction free. Cette fonction est déclarée dans le fichier d en tête ... Wikipédia en Français

    malloc- est en informatique une fonction de la bibliothèque standard de C permettant d allouer dynamiquement de la mémoire. La libération de la mémoire ainsi réservée s effectue avec la fonction free. Cette fonction est déclarée dans l en tête

    Malloc- En informática, malloc es una subrutina proporcionada en las bibliotecas estándar de los lenguajes de programación C y C ++ para realizar la asignación dinámica de memoria. Justificación El lenguaje de programación C administra la memoria de forma estática o automática. Estático …… Wikipedia

    Malloc- En informática, malloc es una subrutina para el ejercicio de asignación de memoria dinámica en los lenguajes de programación C y C ++. Es una abreviatura del inglés Memory Allocation. Forma parte de la biblioteca estándar stdlib.h para ambos …… Wikipedia Español

    malloc- 1.noun Una subrutina en la biblioteca estándar de lenguajes de programación C para realizar la asignación de memoria dinámica. Compara el comportamiento de nueve mallocs diferentes cuando se usa con trazas de actividad de memoria dinámica de Hummingbird y GNU Emacs. 2. verbo ... Wikcionario

    malloc- ● np. cde. LANGC CMDE Contracción de asignación de memoria. Nom d une fonction très importante de la bibliothèque C, car elle permet d attribuer une partie de la mémoire à un processus. Voir aussi calloc. (D après) ... Dictionnaire d "informatique francophone

    Asignación de memoria dinámica C- C Biblioteca estándar Tipos de datos Clasificación de caracteres Cadenas Matemáticas Entrada / salida de archivos Fecha / hora Localización… Wikipedia

    Puntero (informática)- Este artículo trata sobre el tipo de datos de programación. Para la interfaz de entrada (por ejemplo, un mouse de computadora), consulte Dispositivo señalador. Puntero a apuntando a la dirección de memoria asociada con la variable b. Tenga en cuenta que en este diagrama en particular, la informática ... Wikipedia

    Se cuestiona la relevancia del tema del artículo. Muestre en el artículo la importancia de su tema agregando evidencia de importancia para él de acuerdo con criterios particulares de importancia o, si los criterios particulares de importancia para ... ... Wikipedia

    Puntero colgante- Los punteros colgantes y los punteros salvajes en la programación de computadoras son punteros que no apuntan a un objeto válido del tipo apropiado. Estos son casos especiales de violaciones de seguridad de la memoria. Puntero colgante Los punteros colgantes surgen cuando un objeto es ... ... Wikipedia

Su programa debe proporcionar suficiente memoria para almacenar los datos que se utilizan. Algunas de estas ubicaciones de memoria se asignan automáticamente. Por ejemplo, podemos declarar

char place = "Pork Liver Bay";

y se asignará suficiente memoria para recordar esta línea.

O podemos ser más específicos y pedir una cantidad específica de memoria:

placas int;

Esta descripción asigna 100 ubicaciones de memoria, cada una para almacenar un valor entero.

El lenguaje C no se detiene ahí. Le permite asignar memoria adicional mientras se ejecuta el programa. Suponga, por ejemplo, que está escribiendo un programa interactivo y no sabe de antemano cuántos datos tendrá que ingresar. Puede asignar la cantidad de memoria que necesita (como cree) y luego, si es necesario, requerir más. En la Fig. 15.5 es un ejemplo que usa la función malloc () para hacer precisamente eso. Además, observe cómo un programa de este tipo usa punteros.

/ * agregar memoria si es necesario * /

#incluir

#define STOP "" / * señal para detener la entrada * /

#define BLOCK 100 / * bytes de memoria * /

#define LIM 40 / * limitar la longitud de la línea de entrada * /

#define MAX 50 / * número máximo de líneas de entrada * /

#define DRAMA 20000 / * retardo prolongado * /

tienda de char; / * bloque fuente de memoria * /

char symph; / * receptor de líneas de entrada * /

char * end; / * apunta al final de la memoria * /

char * comienza; / * apunta al comienzo de las líneas * /

int índice = 0; / * número de líneas de entrada * /

int count; / * encimera * /

char * malloc (); / * asignador de memoria * /

comienza = tienda;

fin = comienza + BLOQUE - 1;

put ("Nombra algunas orquestas sinfónicas.");

pone ("Ingrese uno a la vez: presione la tecla [enter] al principio");

put ("líneas para completar su lista. Ok, estoy listo.");

while (strcmp (fgets (symph, LIM, stdin), STOP)! = 0 && index< MAX)

(if (strlen (symph)> end - starts)

(/ * acciones en caso de memoria insuficiente para memorizar los datos de entrada * /

put ("Espera un segundo. Intentaré encontrar más memoria");

fin = comienza + BLOQUE - 1;

para (cuenta = 0; cuenta< DRAMA; count++);

put ("¡Encontré algunos!"); )

strcpy (comienza, sinfía);

comienza = comienza + strlen (sinfía) + 1;

si (++ índice< MAX)

printf ("Esto es% d. Continúa si quieres.n", índice); )

put ("Ok, esto es lo que tengo:");

para (cuenta = 0; cuenta< index; count ++)

pone (comienza);

ARROZ. 15,5. Un programa que agrega memoria a pedido.

Aquí hay una muestra de cómo funciona el programa:

Nombra varias orquestas de orquestas sinfónicas.

Introdúzcalos uno a la vez; presione la tecla [enter] al principio

líneas para completar nuestra lista. OK estoy listo.

Sinfónica de San Francisco.

Esto es 1. Continúe si lo desea.

Sinfónica de Chicago

Esto es 2. Continúe si lo desea.

Filarmónica de Berlín

Esto es 3. Continúe si lo desea.

Cámara de Moscú

Este es 4. Continúe si lo desea. Sinfónica de Londres

Este es 5. Continúe si lo desea. Filarmónica de Viena

Espera un segundo. Intentaré encontrar memoria adicional.

¡Encontrado un poco!

Este es 6. Continúe si lo desea.

Sinfónica de Pittsburgh

Este es 7. Continúe si lo desea.

Ok, esto es lo que tengo:

Sinfónica de San Francisco

Sinfónica de Chicago

Filarmónica de Berlín

Cámara de Moscú

Sinfónica de Londres

Filarmónica de Viena

Sinfónica de Pittsburgh

Primero, veamos qué hace la función malloc ()... Toma un argumento entero sin signo que representa el número de bytes de memoria necesarios. Entonces, malloc (BLOQUE) requiere 100 bytes. La función devuelve un puntero al tipo carbonizarse al comienzo de un nuevo bloque de memoria. Usamos la descripción

char * malloc ();

para advertir al compilador que malloc () devuelve un puntero para escribir carbonizarse... Por lo tanto, asignamos el valor de este puntero a un elemento de matriz. empieza por operador

comienza = malloc (BLOQUE);

Ok, veamos ahora el proyecto del programa, que es recordar todas las líneas originales en una fila en una matriz grande. Tienda... Queremos usar empieza para referirse al comienzo de la primera línea, comienza [l]- la segunda línea, etc. En una etapa intermedia, el programa ingresa una línea en una matriz sinfa... Nosotros usamos fgets () en lugar de obtiene () para limitar la cadena de entrada a la longitud de la matriz sinfa.

ARROZ. 15.6. Líneas de sinfía consecutivas escritas en la matriz de la tienda.

Antes de copiar sinfa v Tienda, tenemos que comprobar si queda suficiente espacio para ello. Puntero fin se refiere al final de la memoria y el valor actual empieza se refiere al comienzo de la memoria no utilizada. Entonces podemos comparar la diferencia entre estos dos punteros con la longitud sinfa y determine si queda suficiente memoria.

Si no hay suficiente espacio, llamamos malloc () para preparar memoria adicional. Nosotros definimos empieza al comienzo de un nuevo bloque de memoria, un fin- al final del nuevo bloque. Tenga en cuenta que no tenemos un nombre para esta nueva memoria. No es, por ejemplo, una extensión Tienda... Solo tenemos las designaciones de punteros que se refieren a una nueva área de memoria.

Cuando el programa se ejecuta, cada nueva línea es referenciada por un elemento de la matriz de punteros. empieza... Algunas líneas están en Tienda, otros, en una o más áreas nuevas de la memoria.

Pero mientras tengamos punteros, podemos trabajar con cadenas, como nos muestra la parte impresa del programa.

Así utilizado mаllос ()... Pero suponga que quiere trabajar con la memoria como En t, pero no carbonizarse... También puedes usar aquí mаllос ()... He aquí cómo hacerlo:

char * malloc (); / * todavía se describe como un puntero a char * /

int * newmem;

newmem = (int *) malloc (l00); / * usar la operación de fundición * /

Nuevamente se requieren 100 bytes. La operación de conversión convierte el valor devuelto por un puntero en un tipo carbonizarse, en un puntero al tipo En t... Si, como en nuestro sistema, En t toma dos bytes de memoria, esto significa que newmem + 1 incrementará el puntero en dos bytes, es decir, lo moverá al siguiente entero. Esto también significa que se pueden usar 100 bytes para almacenar 50 enteros.

Otra posibilidad de asignación de memoria se da mediante el uso de la función sallos ():

char * calloc ();

long * newmem;

newmem = (largo *) calloc (100, tamaño de (largo));

Igual que malloc () función sallos () devuelve un puntero a carbonizarse... Debe utilizar el operador de conversión si desea recordar un tipo diferente. Esta nueva función tiene dos argumentos y ambos deben ser enteros sin signo. El primer argumento contiene el número de ubicaciones de memoria necesarias. El segundo argumento es el tamaño de cada celda en bytes. En nuestro caso largo