malloc de tamaño cero [duplicado]


Esta pregunta ya tiene una respuesta aquí:

Pregunta muy simple, hice el siguiente programa:

#include <stdlib.h>
int main(int argc, char ** argv)
{
    void * ptr;
    ptr = malloc(0);
    free(ptr);
}

Y no segfault en mi máquina. ¿Es un comportamiento portátil de stdlib malloc y libre, o estoy buscando problemas ?

Editar: Lo que parece no portable es el valor devuelto por malloc. La pregunta es sobre la combinación malloc ( 0) + free, no el valor de ptr.

 42
Author: shodanex, 2009-07-02

7 answers

El comportamiento está definido por la implementación, recibirá un puntero NULO o una dirección. Sin embargo, llamar gratis para el puntero recibido no debería causar un problema ya que:

  • free (NULL) está bien, no se realiza ninguna operación
  • libre (dirección) está bien, si la dirección fue recibida de malloc (u otros como calloc etc.)
 56
Author: Key,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-02 08:39:29

Se permite devolver NULL, y se permite devolver un puntero no NULO no puedes desreferenciar. Ambas formas están sancionadas por el estándar (7.20.3):

Si el tamaño del espacio solicitado es cero, el comportamiento es definido por la implementación: o se devuelve un puntero nulo, o el comportamiento es como si el tamaño fuera algún valor distinto de cero, excepto que el el puntero devuelto no se utilizará para acceder a un objeto.

 24
Author: dfa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-02 08:30:35

Perdón por la molestia, debería haber leído las páginas del manual:

Malloc () asigna bytes de tamaño y devuelve un puntero a la memoria asignada. La memoria no se borra. Si size es 0, entonces malloc () devuelve NULL, o a valor de puntero único que más tarde se puede pasar con éxito a free().

Free () libera el espacio de memoria apuntado por ptr, que debe haber sido devuelto por una llamada anterior a malloc (), calloc () o realloc (). De lo contrario, o si free (ptr) ya se ha llamado antes, se produce un comportamiento indefinido. Si ptr es NULL, no se realiza ninguna operación.

Parece que es cierto al menos para el libc de gnu

 4
Author: shodanex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-02 08:31:00

Según el estándar c

7.20.3 Si el tamaño del espacio solicitado es cero, el comportamiento está definido por la implementación: o 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.

 2
Author: rohittt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-02 08:31:37

Actualizado teniendo en cuenta los comentarios de libt & Pax:

El comportamiento de llamar a malloc(0) es dependiente de la implementación o, en otras palabras, no portable e indefinido.

Enlace a CFaq pregunta para más detalles.

 1
Author: Aditya Sehgal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-03 05:35:02

Aunque podría ser legal C/C++, es indicativo de problemas más grandes. Generalmente lo llamo 'slopiness puntero'.

Ver " No hacer suposiciones sobre el resultado de malloc (0) o calloc(0)", https://www.securecoding.cert.org/confluence/display/seccode/VOID+MEMxx-A.+Do+not+make+assumptions+about+the+result+of+malloc%280%29+or+calloc%280%29.

 0
Author: Jeffrey Walton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-24 16:24:16

En mi experiencia, he visto que malloc (0) devuelve un puntero que puede ser liberado. Pero, esto causa SIGSEGV en posteriores sentencias malloc (). Y esto fue muy aleatorio.

Cuando agregué un cheque, para no llamar a malloc si el tamaño a asignar es cero, me deshice de esto.

Por lo tanto, sugeriría no asignar memoria para el tamaño 0.

-Ashutosh

 -2
Author: Ashutosh Singhal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-04 06:34:20