2012-03-15 11 views
11

El siguiente código devuelve una dirección cuando se ejecuta en Windows, aunque esperaba que devolviera NULL.¿Por qué malloc (0) devuelve una dirección no nula en Windows?

int main() 
{ 
    char *ptr = NULL; 
    ptr = malloc(0); 
    printf("malloc returned = %u\n", ptr); 

} 

¿Qué podría haber dado lugar a una implementación de malloc? ¿Hay alguna razón detrás de esto?

Dado que esta es una memoria de 0 bytes, no experimenté ningún dato. Pero, ¿se puede usar este recuerdo para cualquier cosa?

Respuesta

9

Es sólo el tamaño mínimo que está solicitando. Y puesto que no hay bloques de longitud cero en el montón de Win32, puede:

void *p = malloc(0); 
// ... do some stuff in between... 
realloc(p, n); 

que en su mayoría deben dar lugar a la reutilización de un bloque de la pila (si tienes suerte y el nuevo tamaño es pequeño). Una optimización oportunista menor (o una desaceleración, según el contexto y los niveles de café en la sangre).

Este es un ejemplo simplificado. La situación real podría ser una clase que asigna un búfer cuando se crea y también permite que crezca. Si las entradas son molestas de controlar, puede dejar que haga esa asignación de búfer de tamaño cero.

+0

+1, ya que he visto a 1 persona usar esto para su "ventaja" cuando no quería un caso especial en un bucle que pudiera hacer crecer la memoria malloc/real. – JimR

+1

Puede pasar un puntero nulo en 'realloc', sin embargo, este truco no es esencial. Podrías decir 'void * p = 0;'. –

+0

@Steve No es realmente un truco. Es un artefacto de programación y especificaciones de plataformas sueltas. Sin pruebas, no está claro cómo se comportaría HeapRealloc (montón, HEAP_REALLOC_IN_PLACE_ONLY, 0, 4), por ejemplo. – ActiveTrayPrntrTagDataStrDrvr

7

Eso es contestada dentro del FAQ comp.lang.c: http://c-faq.com/ansi/malloc0.html

El/ISO estándar ANSI dice que puede hacer cualquiera; el comportamiento está definido por la implementación (ver pregunta 11.33). El código portátil debe tener cuidado de no llamar a malloc (0) o estar preparado para la posibilidad de un retorno nulo.

+0

Pero, ¿qué haría una implementación elegir devolver algún valor válido? ¿No tiene sentido devolver NULL en todos los casos? – Jay

+3

No necesariamente. Me estremezco al adivinar los escritores del compilador, pero un implementador podría querer que malloc devuelva 'null' solo si la memoria no se puede asignar realmente. – CAbbott

+1

@Jay: dado que la implementación es libre de hacer bien, bien podría decidir hacer lo que sea menos código. Es razonable decidir no preocuparse por escribir una línea adicional de código para probar la entrada de 0 y devolver un puntero nulo. Por otra parte, si la implementación ya tiene una prueba de que el tamaño requerido no es absurdamente grande (y devolverá un puntero nulo si lo es), entonces podría ser tan fácil verificar absurdamente-enorme-o-cero. –

8

Para responder a la segunda parte de su pregunta no, la memoria no se puede usar para nada, ya que "la parte accesible" es 0 bytes a partir de la dirección devuelta.

IIRC se garantiza sin embargo que si la implementación no es nula, se tratará de una dirección diferente de cualquier otro bloque de memoria asignado actualmente. Entonces, en teoría, podría usar la dirección como una identificación única temporal (del tipo de puntero), aunque obviamente hay muchas otras formas de obtener una identificación única. E incluso si fuera a usarlo para eso, malloc(1) funcionaría igual de bien que malloc(0) y sería más portátil.

0

NO es inútil. Se espera que los bloques que se devuelven desde malloc sean únicos. Por lo tanto, cada bloque devuelto por malloc lleva tanto los datos dentro del bloque como un identificador único para él, que es su dirección. Si la última propiedad es importante, y el hecho de que no contiene datos no es un problema, entonces es útil.

Sin embargo, como se mencionó es una excelente manera de escribir código no portátil. Sin embargo, esto NO es lo mismo que un código ilegal, y es perfectamente válido para una implementación que lo soporte (como aparentemente windows lo hace).

Cuestiones relacionadas