2010-07-04 31 views
10

1)
¿Para qué tipos de datos debo asignar memoria con malloc?¿Cuándo debo usar malloc para asignar memoria?

  • Para tipos como estructuras, punteros, excepto los tipos de datos básicos, como int
  • Para todos los tipos?

2)
qué puedo ejecutar este código? ¿Por qué no se cuelga? Supuse que primero debía asignar memoria para la estructura.

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

typedef unsigned int uint32; 
typedef struct 
{ 
    int a; 
    uint32* b; 
} 
foo; 

int main(int argc, char* argv[]) 
{ 
foo foo2; 
foo2.a = 3; 
foo2.b = (uint32*)malloc(sizeof(uint32)); 
*foo2.b = 123; 
} 

¿No sería mejor usar

foo* foo2 = malloc(sizeof(foo)); 

3) Cómo es foo.b establecido? ¿Es la memoria aleatoria de referencia o NULL?

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

typedef unsigned int uint32; 
typedef struct 
{ 
    int a; 
    uint32* b; 
} 
foo; 

int main(int argc, char* argv[]) 
{ 
foo foo2; 
foo2.a = 3; 

} 

Respuesta

9

Edita para resolver tus preguntas numeradas.

  1. No hay tipos de datos que deba asignar con malloc. Solo si desea que un tipo de puntero apunte a una memoria válida debe usar el operador & (dirección-de) único o malloc() o alguna función relacionada.

  2. No hay nada malo con su código - la línea:

    foo foo2; 
    

    asigna una estructura en la pila - entonces todo funciona con normalidad. Las estructuras no son diferentes en este sentido que cualquier otra variable. No es mejor o peor usar variables automáticas (asignación de pila) o globales malloc(), son todas diferentes, con diferente semántica y diferentes razones para elegirlas.

  3. En su ejemplo en el n. ° 3, el valor de foo2.b no está definido. Cualquier variable automática tiene un valor indefinido e indeterminado hasta que la inicialice explícitamente.

1

Puede hacerlo, pero esto no es suficiente.

Porque, el segundo campo es un puntero, que debe establecerse en una dirección válida. Una de las formas de hacerlo es asignando memoria (con malloc).

Para su primera pregunta - use malloc cuando DEBE gestionar la vida del objeto manualmente.

Por ejemplo, el segundo código podría ser reescrita como:

int main(int argc, char* argv[]) 
{ 
foo foo2; uint32 b; 
foo2.a = 3; 
foo2.b = &b; 
*foo2.b = 123; 
} 

Esto es mejor, porque la vida es la misma, y ​​la memoria está ahora en la pila - y no necesita ser liberado.

2

foo foo2; asigna automáticamente la estructura en la pila, y se desasigna automáticamente cuando termina la función de cerramiento (main en este caso).

Solo necesita asignar memoria en el montón, utilizando malloc, si necesita que la estructura persista una vez que finaliza el ámbito adjunto. También puede necesitar hacer esto cuando el objeto es demasiado grande para caber en la pila.

1

La memoria para la instancia struct ("foo2") se asignará en la pila; no es necesario asignar memoria para esto usted mismo. Si asigna usando malloc, asegúrese de liberar la memoria más adelante.

18

Todos los tipos en C se pueden asignar de forma dinámica, automática (en la pila) o estáticamente. El problema no es el tipo, sino el tiempo de vida que desea: utiliza malloc cuando desea que un objeto exista fuera del alcance de la función que lo creó, o cuando no sabe de antemano qué magnitud necesita.

+1

+1: C99 permite el uso de asignación de pila para estructuras de longitud variable (bueno, matrices, pero eso es suficiente para hacer todo). Pero no lo recomiendo para nada significativo de todos modos; en la práctica, la pila tiende a ser * mucho * más pequeña que la pila. (También trabajo mucho con código donde la duración de la estructura de datos no coincide con la vida útil de la estructura de pila). –

+0

+1 y +1. Se puede mitigar el requisito del alcance de exo función elevando malloc() hasta la función de llamada, y no forzando a malloc() a llamarse millones de veces en lugar de una vez, Y esto a menudo también es una gran mejora en el rendimiento. Esto se puede hacer, y normalmente debería hacerse, incluso si la persona que llama desconoce el tamaño, donde la función llama a realloc() si la memoria es insuficiente. Digo esto porque la persona que llama necesita el puntero a la memoria libre() una vez que el ciclo ha terminado de llamar a su función. SIEMPRE malloc()/calloc() y free() en el mismo ámbito. ¡SIEMPRE! – RocketRoy

3

Debe asignar con malloc cualquier memoria que desee que se administre manualmente, en lugar de automáticamente. No importa si lo que está almacenado allí es int o double o struct o cualquier cosa; malloc tiene que ver con la gestión manual de la memoria.

Cuando crea una variable sin malloc, se almacena en la pila y cuando se sale del alcance, su memoria se recupera automáticamente. Una variable queda fuera del alcance cuando la variable ya no es accesible; p.ej. cuando el bloque o la función en la que se declaró la variable termina.

Al asignar memoria con malloc, se almacena en el montón y malloc devuelve un puntero a esta memoria. Esta memoria no se recuperará hasta que llame al free, independientemente de si un puntero permanece accesible o no (cuando no hay punteros que permanecen en la memoria asignada en el montón, esta es una pérdida de memoria ). Esto significa que usted gana la habilidad de continuar usando la memoria que asignó después del bloque o función que fue asignada en los extremos, pero por otro lado ahora tiene la responsabilidad de desasignarlo manualmente cuando termine de usarlo.

En su ejemplo, foo2 está en la pila, y se desasignará automáticamente cuando finalice main. Sin embargo, la memoria apuntada por foo2.b será no se desasignará automáticamente, ya que está en el montón. Esto no es un problema en su ejemplo porque toda la memoria se devuelve al sistema operativo cuando finaliza el programa, pero si estuviera en una función que no sea main, habría sido una pérdida de memoria.

2

2) ¿Por qué puedo ejecutar este código? ¿Por qué no se cuelga?

El código nunca se refiere a memoria indefinida o NULL. ¿Por qué se estrellaría? (Tiene una pérdida de memoria tal como está escrita, pero es probable porque solo muestra una parte del código y en el programa dado no es un problema).

El código alternativo que sugiere también funcionará, aunque se haya devuelto la memoria desde malloc tampoco está inicializado de manera predeterminada.(Una vez trabajé con un asignador de memoria personalizado que llenaba los bloques de memoria devueltos por defecto con ?. Sigue siendo perfectamente legal según las reglas. Tenga en cuenta que calloc devuelve un puntero a la memoria inicializada en cero; úselo si eso es lo que desea)

3) ¿Cómo se establece foo.b? ¿Es la memoria aleatoria de referencia o NULL?

Memoria aleatoria. Las estructuras asignadas de pila no se inicializan para usted.

+0

¿La duración de la vida de foo.b se extiende a toda la ejecución del programa o finaliza con la función? @DonalFellows – jdyg

Cuestiones relacionadas