como - ¿Cuál es el punto en malloc(0)?
malloc sizeof c++ (17)
Acabo de ver este code:
artist = (char *) malloc(0);
y me preguntaba por qué uno haría esto?
Aquí está el análisis después de ejecutar con la herramienta de verificación de memoria valgrind.
==16740== Command: ./malloc0
==16740==
p1 = 0x5204040
==16740==
==16740== HEAP SUMMARY:
==16740== in use at exit: 0 bytes in 0 blocks
==16740== total heap usage: 2 allocs, 2 frees, 1,024 bytes allocated
==16740==
==16740== All heap blocks were freed -- no leaks are possible
y aquí está mi código de muestra:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
//int i;
char *p1;
p1 = (char *)malloc(0);
printf("p1 = %p/n", p1);
free(p1);
return 0;
}
Por defecto, se asignan 1024 bytes. Si aumento el tamaño de malloc, los bytes asignados aumentarán en 1025 y así sucesivamente.
De acuerdo con la respuesta de y la página man de malloc, escribí algunos ejemplos para probar. Y descubrí que malloc (0) siempre le dará un valor único. Ver mi ejemplo:
char *ptr;
if( (ptr = (char *) malloc(0)) == NULL )
puts("Got a null pointer");
else
puts("Got a valid pointer");
La salida será "Obtuvo un puntero válido", lo que significa que ptr
no es nulo.
El comportamiento de malloc (0) es específico de la implementación. La biblioteca puede devolver NULL o tener el comportamiento malloc normal, sin memoria asignada. Lo que sea que haga, debe estar documentado en alguna parte.
Por lo general, devuelve un puntero que es válido y único, pero NO debe desreferenciarse. También tenga en cuenta que PUEDE consumir memoria a pesar de que en realidad no asignó nada.
Es posible reasignar un puntero no nulo malloc (0).
Tener un Malloc (0) al pie de la letra no es muy útil. Se usa principalmente cuando una asignación dinámica es de cero bytes y no le importó validarla.
El estándar C dice:
Si no se puede asignar el espacio, se devuelve un puntero nulo. Si el tamaño del espacio solicitado es cero, el comportamiento se define en la implementación: 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 utilizará para acceder a un objeto.
Por lo tanto, malloc(0)
podría devolver NULL
o un puntero válido que no se puede desreferenciar . En cualquier caso, es perfectamente válido llamar a free()
en él.
Realmente no creo que malloc(0)
tenga mucho uso, excepto en los casos en que malloc(n)
se llama en un bucle, por ejemplo, y n
podría ser cero.
Al mirar el código en el enlace, creo que el autor tenía dos conceptos erróneos:
-
malloc(0)
devuelve un puntero válido siempre , y -
free(0)
es malo.
Entonces, se aseguró de que el artist
y otras variables siempre tuvieran un valor "válido". El comentario dice lo siguiente: // these must always point at malloc''d data
.
En Windows:
-
void *p = malloc(0);
asignará un búfer de longitud cero en el montón local. El puntero devuelto es un puntero de montón válido. -
malloc
finalmente llama aHeapAlloc
usando el montón de tiempo de ejecución C predeterminado que luego llama aRtlAllocateHeap
, etc. -
free(p);
usaHeapFree
para liberar el buffer de 0-length en el montón. No liberarlo daría lugar a una pérdida de memoria.
Es cierto que nunca he visto esto antes, esta es la primera vez que veo esta sintaxis, podría decirse, un caso clásico de exceso de funciones. En relación con la respuesta de Reed, me gustaría señalar que hay algo similar, que parece una función sobrecargada realloc
:
- foo no es NULL y el tamaño es cero,
realloc(foo, size);
. Cuando pasa un puntero no nulo y un tamaño de cero a realloc, realloc se comporta como si hubiera llamado libre (...) - foo es NULL y el tamaño no es cero y es mayor que 1,
realloc(foo, size);
. Cuando pasa un puntero NULL y el tamaño no es cero, realloc se comporta como si hubiera llamado malloc (...)
Espero que esto ayude, Saludos, Tom.
Hay muchas respuestas verdaderas a medias aquí, así que aquí están los hechos concretos. La página de manual para malloc()
dice:
Si el tamaño es 0, entonces malloc () devuelve NULL o un valor de puntero único que luego se puede pasar a free ().
Eso significa que no hay absolutamente ninguna garantía de que el resultado de malloc(0)
sea único o no NULO. La única garantía es proporcionada por la definición de free()
, de nuevo, aquí está lo que dice la página man:
Si ptr es NULL, no se realiza ninguna operación.
Por lo tanto, cualquiera que sea el retorno de malloc(0)
, se puede pasar de forma segura a free()
. Pero también puede un puntero NULL
.
En consecuencia, escribiendo artist = malloc(0);
de ninguna manera es mejor que escribir artist = NULL;
Hay una respuesta en otro lugar en esta página que comienza "malloc (0) devolverá una dirección de memoria válida y cuyo rango dependerá del tipo de puntero al que se le asigna memoria". Esta afirmación es incorrecta (no tengo suficiente reputación para comentar directamente esa respuesta, por lo que no puedo poner este comentario directamente debajo).
Hacer malloc (0) no asignará automáticamente la memoria del tamaño correcto. La función malloc desconoce a qué arroja su resultado. La función malloc se basa únicamente en el número de tamaño que usted da como argumento. Necesita hacer malloc (sizeof (int)) para obtener suficiente almacenamiento para mantener un int, por ejemplo, no 0.
No estoy seguro, de acuerdo con algún código fuente malloc aleatorio que encontré, una entrada de 0 da como resultado un valor de retorno de NULL. Entonces, es una manera loca de configurar el puntero del artista a NULL.
http://www.raspberryginger.com/jbailey/minix/html/lib_2ansi_2malloc_8c-source.html
Para responder realmente a la pregunta hecha: no hay razón para hacer eso
Por qué no deberías hacer esto ...
Como el valor de retorno de malloc depende de la implementación, puede obtener un puntero NULL o alguna otra dirección. Esto puede terminar creando desbordamientos de memoria intermedia (heap-buffer) si el código de administración de errores no verifica tanto el tamaño como el valor devuelto, lo que genera problemas de estabilidad (bloqueos) o incluso problemas de seguridad peores.
Considere este ejemplo, donde el acceso adicional a la memoria a través de la dirección devuelta dañará el montón si el tamaño es cero y la implementación devuelve un valor no NULO.
size_t size;
/* Initialize size, possibly by user-controlled input */
int *list = (int *)malloc(size);
if (list == NULL) {
/* Handle allocation error */
}
else {
/* Continue processing list */
}
Vea esta página de codificación segura de las normas de codificación CERT, donde tomé el ejemplo anterior para leer más.
Sé que han pasado cinco años, pero mi respuesta puede agregar algo y tengo una reputación que mantener.
malloc(0);
se puede usar en situaciones donde no se conoce la duración exacta de lo que viene. Si un resultado de longitud cero también es un resultado posible, no hay uso de comenzar con un tamaño mínimo asignado. Por ejemplo, buffers. Si lee una cantidad variable de bytes desde algún lugar, su memoria intermedia puede crecer. Puedes hacer crecer tu buffer con realloc()
. Pero realloc necesita un puntero a la memoria que ya está malloc
ed o calloc
ed, y luego es cuando usas malloc(0);
.
char* buffer = malloc(0);
int bytesread = 0;
do
{
//read n bytes from somewhere
buffer = realloc(buffer, bytesread + n); //expand the buffer
//check it is properly allocated
//copy the newly read bytes to the buffer
bytesread += n;
}
while (there_is_still_a_chance_of_reading_more_bytes);
//do something with the complete buffer
free(buffer); //does not really need if(buffer);
Por supuesto. hay otras consideraciones: si conoce la cantidad de bytes que se leerán o si ese número será grande, leer repetidamente números pequeños de bytes y usar memset
no es muy eficiente.
Según las especificaciones, malloc(0) devolverá "un puntero nulo o un puntero único que se puede pasar con éxito a free ()".
Esto básicamente le permite asignar nada, pero aún así pasar la variable "artista" a una llamada a free () sin preocupaciones. A efectos prácticos, es prácticamente lo mismo que hacer:
artist = NULL;
Solo para corregir una falsa impresión aquí:
artist = (char *) malloc(0);
nunca volverá NULL
; no es lo mismo que artist = NULL;
. Escribe un programa simple y compara al artist
con NULL
. if (artist == NULL)
es falso y if (artist)
es verdadero.
malloc (0) devolverá NULL o un puntero válido que se puede pasar correctamente a free. Y aunque parece que el recuerdo al que apunta es inútil o no se puede escribir ni leer, eso no siempre es cierto. :)
int *i = malloc(0);
*i = 100;
printf("%d", *i);
Esperamos un error de segmentación aquí, pero sorprendentemente, ¡esto imprime 100! Es porque Malloc realmente pide una gran cantidad de memoria cuando llamamos malloc por primera vez. Cada llamada a malloc después de eso, usa memoria de ese gran pedazo. Solo después de que se ha terminado la gran parte, se solicita nueva memoria.
Uso de malloc (0): si se encuentra en una situación en la que desea que las llamadas malloc posteriores sean más rápidas, al llamar a malloc (0) debería hacerlo por usted (excepto en casos límite).
malloc(0)
devolverá una dirección de memoria válida y cuyo rango dependerá del tipo de puntero al que se le asigna la memoria. También puede asignar valores al área de memoria, pero esto debe estar dentro del rango con el tipo de puntero que se está utilizando. También puede liberar la memoria asignada. Explicaré esto con un ejemplo:
int *p=NULL;
p=(int *)malloc(0);
free(p);
El código anterior funcionará bien en un compilador gcc
en una máquina Linux. Si tiene un compilador de 32 bits, puede proporcionar valores en el rango entero, es decir, -2147483648 a 2147483647. Lo mismo se aplica a los caracteres también. Tenga en cuenta que si se cambia el tipo de puntero declarado, el rango de valores cambiará independientemente del tipo de malloc
, es decir,
unsigned char *p=NULL;
p =(char *)malloc(0);
free(p);
p
tomará un valor de 0 a 255 de char ya que se declara como unsigned int.
malloc(0)
no tiene ningún sentido para mí, a menos que el código se base en el comportamiento específico de la implementación. Si el código está destinado a ser portátil, entonces tiene que dar cuenta del hecho de que un retorno NULL de malloc(0)
no es un error. Entonces, ¿por qué no simplemente asignar NULL al artist
todos modos, ya que ese es un resultado exitoso válido, y es menos código, y no hará que los programadores de mantenimiento se tomen su tiempo averiguándolo?
malloc(SOME_CONSTANT_THAT_MIGHT_BE_ZERO)
o malloc(some_variable_which_might_be_zero)
quizás podrían tener sus usos, aunque nuevamente hay que tener especial cuidado de no tratar un retorno NULO como un error si el valor es 0, pero se supone que un tamaño 0 es correcto.