2011-02-07 13 views

Respuesta

1

Yo diría que es principalmente específico de la implementación. Algunas implementaciones pueden fallar. Algunos pueden tener otras partes del programa que fallan antes de que realloc lo haga. Siempre esté a la defensiva y verifique si falla.

Y recuerde liberar el antiguo puntero que ha intentado realocar.

ptr=realloc(ptr,10); 

SIEMPRE es una posible pérdida de memoria.

siempre hacerlo bien como esto:

void *tmp=ptr; 
if(ptr=realloc(ptr,10)==NULL){ 
    free(tmp); 
    //handle error... 
} 
+0

Creo que lo único que dice la norma al respecto es que se devuelve un puntero nulo "[i] f no se puede asignar el espacio", nada más específico sobre las razones. – Mormegil

+0

Tirar los datos antiguos cuando no puede dejar espacio para nuevos datos probablemente no sea el comportamiento correcto para la mayoría de las aplicaciones ... –

+0

@R .. Bueno, eso es cierto. Solo estaba advirtiendo sobre la pérdida de memoria común – Earlz

0

Tiene dos preguntas.

Las posibilidades de que malloc o realloc fallen son insignificantes en la mayoría de los sistemas modernos. Esto solo ocurre cuando te quedas sin memoria virtual. Su sistema fallará al acceder a la memoria y no al reservarla.

W.r.t error realloc y malloc son casi iguales. La única razón por la que puede fallar realloc es que le da un argumento malo, es decir, memoria que no se ha asignado con malloc o realloc o que anteriormente ha sido free d.

Editar: En vista del comentario de R. Sí, puede configurar su sistema para que falle cuando lo asigne. Pero antes que nada, AFAIK, este no es el predeterminado. Necesita los privilegios para configurarse de esa manera y como programador de aplicaciones esto no es nada con lo que pueda contar. En segundo lugar, incluso si tuviera un sistema que está configurado de esa manera, solo se producirá un error cuando el espacio disponible para el intercambio se haya agotado. Por lo general, su máquina no podrá usarse mucho antes: realizará cálculos mecánicos en su disco duro (intercambio AKA).

+0

El fallo en el * acceso * a * la asignación * no es un comportamiento "moderno". Es un comportamiento perezoso. La contabilidad de compromiso es difícil, y al principio del desarrollo de Linux, todos eran demasiado perezosos para hacerlo bien. Los sistemas robustos Unix han llevado a cabo una contabilidad de compromiso adecuada durante décadas, y en estos días Linux también se puede configurar para una contabilidad adecuada. –

+0

Argumentaría que no es responsabilidad del desarrollador de la aplicación preocuparse por la posibilidad de que se active el exceso de compromiso. No hay una buena solución para la posibilidad de que su programa se bloquee al acceder a la memoria que ya se asignó "con éxito". Puedes atrapar 'SIGSEGV', pero ¿qué haces si lo atrapas? Supongo que podrías reasignar una página 'MAP_SHARED' desde un archivo ficticio encima de ella y luego regresar desde el manejador de señal, y hacer que la persona que llama detecte que esto sucedió ... –

+0

@R .: Después de la asignación, podrías atrapar temporalmente' SIGSEGV' y 'SIGBUS' y recorrer las páginas para acceder a ellas. Con eso, al menos podrías limitar el error y luego fallar con gracia. La sobrecarga inicial para una asignación sería notable, pero el costo amortizado si toda esa memoria realmente se usa sería tolerable, creo. –

10

Cualquiera de las funciones de asignación (malloc, realloc, calloc, y en POSIX, posix_memalign) podrían fallar por cualquiera de las siguientes razones, y posiblemente otros:

  • que haya agotado su dirección virtual completa espacio, o al menos la parte útil de él. En una máquina de 32 bits, solo hay 4 GB de direcciones, y posiblemente 1 GB esté reservada para ser utilizada por el núcleo del sistema operativo. Incluso si su máquina tiene 16 GB de memoria física, un solo proceso no puede usar más de las direcciones que tiene.
  • No ha agotado su espacio de direcciones virtuales, pero lo ha fragmentado tanto que no hay disponible un rango contiguo de direcciones del tamaño solicitado. Esto podría suceder (en una máquina de 32 bits) si asigna con éxito 6 bloques de 512MB, libere todos los demás, luego intente asignar un bloque de 1GB. Por supuesto, hay muchos otros ejemplos con tamaños de memoria más pequeños.
  • Su máquina se ha quedado sin memoria física, ya sea debido a que su propio programa lo ha usado todo, o porque otros programas que se ejecutan en la máquina lo han usado todo. Algunos sistemas (Linux en la configuración predeterminada) van a sobrecommitir, lo que significa malloc no fallará en esta situación, pero en su lugar el sistema operativo matará más adelante uno o más programas cuando se da cuenta de que no hay memoria física suficiente para todos.Pero en sistemas robustos (incluido Linux con overcommit desactivado), malloc fallará si no queda memoria física.

Tenga en cuenta que, estrictamente hablando, las funciones de asignación pueden fallar en cualquier momento por cualquier motivo. Minimizar la falla es un problema de calidad de implementación. También es posible que realloc falle, incluso cuando reduzca el tamaño de un objeto; esto podría suceder en implementaciones que segregan estrictamente las asignaciones por tamaño. Por supuesto, en este caso, simplemente podría continuar utilizando el objeto antiguo (más grande).

4

usted debe pensar en realloc como trabajar de esta manera:

void *realloc(void *oldptr, size_t newsize) 
{ 
    size_t oldsize = __extract_size_of_malloc_block(oldptr); 
    void *newptr = malloc(newsize); 

    if (!newptr) 
    return 0; 

    if (oldsize > newsize) 
    oldsize = newsize; 

    memcpy(newptr, oldptr, oldsize); 
    free(oldptr); 
    return newptr; 
} 

Una implementación puede ser capaz de hacer casos concretos de manera más eficiente que eso, pero una aplicación que funciona exactamente como se muestra es 100% correcto. Eso significa que realloc(ptr, newsize) puede fallar en cualquier momento malloc(newsize) habría fallado; en particular, puede fallar incluso si está reduciendo la asignación.

Ahora, en sistemas de escritorio modernos hay un caso fuerte para no tratar de recuperarse de malloc fracasos, pero en lugar de envolver malloc en una función (generalmente llamado xmalloc) que termina el programa inmediatamente si falla malloc; naturalmente, el mismo argumento se aplica al realloc. El caso es:

  1. Los sistemas de escritorio a menudo se ejecutan en modo "overcommit" dónde está el núcleo estará feliz de entregar más espacio de direcciones que puede ser respaldado por RAM + swap, suponiendo que el programa no es en realidad va a utilizar todos de eso Si el programa hace intente utilizarlo todo, terminará a la fuerza. En tales sistemas, malloc solo fallará si agota el espacio de direcciones , que es poco probable en sistemas de 32 bits y casi imposible en sistemas de 64 bits.
  2. Incluso si no está en el modo de sobrecompromiso, las probabilidades son que un sistema de escritorio tenga tanta RAM e intercambio disponibles que, mucho antes de que malloc falle, el usuario se cansará con su disco agónico y terminará a la fuerza tu programa
  3. No hay manera práctica de probar recuperación de una falla de asignación; incluso si tuviera una biblioteca de shim que pudiera controlar exactamente qué llamadas a malloc fallaron (tales calzas son en el mejor de los casos difíciles, en el peor imposibles de crear, dependiendo del sistema operativo) tendría que probar el orden de 2 N patrones de falla, donde N es la cantidad de llamadas a malloc en su programa.

Los argumentos 1 y 2 no se aplican a los sistemas integrados o móviles (todavía!) Pero el argumento 3 sigue siendo válido allí.

El argumento 3 solo se aplica a los programas donde las fallas de asignación se deben verificar y propagar en cada sitio de llamadas. Si tiene la suerte de utilizar C++ tal como está previsto (es decir, con excepciones), puede confiar en que el compilador creará las rutas de recuperación de errores para usted, por lo que la carga de las pruebas es muy reducida. Y en cualquier lenguaje de nivel superior que valga la pena usar hoy en día, tiene excepciones y un recolector de basura, lo que significa que no podría preocuparse por las fallas de asignación aunque quisiera.

Cuestiones relacionadas