2012-08-14 13 views
5

Cotización:No está seguro de la corrección de una oración de K & R - aritmética del puntero | Liberando procedimiento

La prueba si (+ allocbuf ALLOCSIZE - allocp> = n) { comprueba si hay espacio suficiente para satisfacer una petición de n caracteres. Si existe, el nuevo valor de allocp sería como máximo uno más allá del final de allocbuf.

El código que se refiera a:

#define ALLOCSIZE 10000 /* size of available space */ 
static char allocbuf[ALLOCSIZE]; /* storage for alloc */ 
static char *allocp = allocbuf; /* next free position */ 

char *alloc(int n) 
/* return pointer to n characters */ 
{ 
    if (allocbuf + ALLOCSIZE - allocp >= n) { /* it fits */ 
     allocp += n; 
     return allocp - n; /* old p */ 
    } else 
/* not enough room */ 
     return 0; 
} 
void afree(char *p) /* free storage pointed to by p */ 
{ 
    if (p >= allocbuf && p < allocbuf + ALLOCSIZE) 
     allocp = p; 
} 

Entonces, ¿cómo se puede estar más allá de la última posición en allocbuf? Que en mi opinión es allocbuf [9999]

Cualquier cosa más allá de eso, por ejemplo. allocbuf [10000] es incorrecto y es una pérdida de memoria, ¿verdad?


La segunda parte de la pregunta - que a pesar de que afree función de acuerdo a su nombre está suprimiendo el valor guardado en lugares particulares de una matriz. Sin embargo, como puedo ver, ¿solo mueve el "cabezal de grabación" solo unos pocos lugares a la izquierda de una matriz? Los datos guardados allí permanecen intactos.

+0

+1, para el hallazgo. – perilbrain

+1

Si 'allocp' apunta a' allocbuf [10000] ', esto significa que el almacenamiento se utiliza por completo (la última división tenía exactamente' n' entradas) y por lo tanto una subsecuente 'alloc()' devolverá '0'. La cita no dice que se permite el uso de este puntero "ilegal", y de hecho no se devuelve de 'alloc()'. – evnu

+2

Para su información, acceder a la memoria más allá de la que se le asignó es un desbordamiento, no una pérdida de memoria. Una pérdida de memoria está perdiendo la pista de la memoria asignada por lo que no puede liberar esa memoria más adelante. –

Respuesta

5

allocp siempre debe apuntar a la última posición de memoria libre, pero cuando no hay posiciones de memoria libres, será uno más allá del final de allocbuf.

Considere la situación cuando solo queda una sola celda de memoria en el búfer: allocp apuntará a allocbuffer[9999] ya que es la última celda de memoria libre. Ahora, cuando usted hace la llamada a la función alloc(1) la prueba

allocbuf + ALLOCSIZE - allocp >= n 

volverá verdadera como es debido, ya que está intentando asignar un char y hay exactamente un char izquierda. Luego se asignará la última posición de memoria. Ahora allocbuf - allocp == ALLOCSIZE y es uno más allá del final de allocbuf. Pero en ese caso, la prueba mencionada siempre devolverá el valor falso y, por lo tanto, no se accederá a ninguna memoria más allá del alcance allocbuf.


Sobre su pregunta sobre afree: El valor inicial de la memoria devuelta por malloc no está definido. Esto significa que nunca puede hacer suposiciones al respecto y debe sobrescribirlo antes de su uso. Por lo tanto, afree no tiene que borrar ningún dato contrario a lo que está asumiendo. Está perfectamente bien que simplemente marque que ya no está en uso y disponible para futuras asignaciones.

En una nota al margen hay una función muy similar a malloc llamada calloc que después de asignar el bloque de memoria solicitado lo inicializa a cero.

+1

Se permite un puntero al elemento uno pasado el final de una matriz. – ecatmur

+0

@paldepind - muchas gracias! ¿Puedes responder la segunda parte sobre el procedimiento libre también? –

+0

¡De nada! He actualizado la respuesta. – paldepind

2

En cuanto a la segunda parte de su pregunta: funciones de gestión de memoria como afree() o la biblioteca Cfree() No normalmente cero o borrado de memoria. Simplemente lo ponen a disposición para su reutilización. Esto es bueno porque no paga el costo de rendimiento. Desafortunadamente, puede enmascarar errores como el uso de memoria que ya no posee.

Algunos gestores de montón pueden poner a cero la memoria o llenarla con valores especiales cuando llama al free() por razones de seguridad o para ayudar a la depuración. Esto no es requerido por el estándar y usted tendría que habilitar específicamente este comportamiento.

Cuestiones relacionadas