usar como array c memory-management malloc free

como - malloc sizeof



Si `malloc(0)` devuelve un puntero no nulo, ¿puedo pasarlo a `free`? (2)

El estándar C99 (en realidad WG14 / N1124. Borrador del Comité - 6 de mayo de 2005. ISO / IEC 9899: TC2) dice sobre malloc() :

El puntero devolvió los puntos al inicio (dirección de byte más bajo) del espacio asignado. Si no se puede asignar el espacio, se devuelve un puntero nulo. Si el tamaño del espacio solicitado es cero, el comportamiento es la implementación definida: se devuelve un puntero nulo o el comportamiento es como si el tamaño fuera un valor distinto de cero, excepto que el puntero devuelto no se debe usar para acceder a un objeto

y sobre free() :

De lo contrario, si el argumento no coincide con un puntero devuelto anteriormente por la función calloc, malloc o realloc, o si el espacio ha sido desasignado por una llamada a free o realloc, el comportamiento no está definido.

IEEE Std 1003.1-2008 (POSIX), edición 2016 dice sobre free() :

La función free () hará que el espacio apuntado por ptr sea desasignado; es decir, disponible para una asignación adicional. Si ptr es un puntero nulo, no se realizará ninguna acción. De lo contrario, si el argumento no coincide con un puntero devuelto anteriormente por una función en POSIX.1-2008 que asigna memoria como si fuera malloc (), o si el espacio ha sido desasignado por una llamada a free () o realloc (), el comportamiento no está definido

Entonces, sea lo que sea lo que *alloc() , puede pasar a free() .

En cuanto a las implementaciones actuales de malloc() :

FreeBSD usa el jemalloc contribuido que hace

void * je_malloc(size_t size) { void *ret; size_t usize JEMALLOC_CC_SILENCE_INIT(0); if (size == 0) size = 1; [...]

Mientras que el libmalloc de Apple no

void * szone_memalign(szone_t *szone, size_t alignment, size_t size) { if (size == 0) { size = 1; // Ensures we''ll return an aligned free()-able pointer [...]

El GLIBC también cambia el tamaño solicitado; está utilizando una llamada a esta macro con el tamaño solicitado en bytes como el parámetro para alinear el tamaño a un cierto límite o simplemente al tamaño mínimo de asignación:

#define request2size(req) / (((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? / MINSIZE : / ((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)

He estado leyendo las discusiones sobre cómo se comporta malloc cuando solicita un bloque de tamaño cero.

Entiendo que el comportamiento de malloc(0) está definido por la implementación, y se supone que devuelve un puntero nulo o un puntero no nulo al que no se supone que debo acceder. (Lo cual tiene sentido, ya que no hay garantía de que apunte a ninguna memoria utilizable).

Sin embargo, si obtengo un puntero no nulo y no nulo, ¿puedo pasarlo a la free de la forma habitual? ¿O es ilegal, ya que el puntero que obtengo de malloc(0) puede no apuntar a un bloque de memoria asignada real?

Concretamente, el siguiente código tiene un comportamiento bien definido:

#include <stdio.h> #include <stdlib.h> int main() { int* x = (int*) malloc(0); if (x == NULL) { printf("Got NULL/n"); return 0; } else { printf("Got nonnull %p/n", x); } free(x); // is calling `free` here okay? }


Sí, de hecho debe hacerlo para evitar una posible pérdida de memoria.

El sistema malloc típicamente devuelve un bloque de control oculto en el espacio inmediatamente anterior al puntero, con información como el tamaño de la asignación. Si el tamaño de la asignación es cero, este bloque todavía existe y ocupa memoria, si malloc devuelve no nulo.