Por qué es más seguro usar sizeof (*pointer) en malloc


Dado

struct node
{
     int a;
     struct node * next;
};

A malloc una nueva estructura,

struct node *p = malloc(sizeof(*p));

Es más seguro que

struct node *p = malloc(sizeof(struct node));

¿Por qué? Pensé que eran iguales.

 40
Author: Yu Hao, 2013-06-23

4 answers

Es más seguro porque no tiene que mencionar el nombre del tipo dos veces y no tiene que construir la ortografía adecuada para la versión "desreferenciada" del tipo. Por ejemplo, usted no tiene que "contar las estrellas" en

int *****p = malloc(100 * sizeof *p);

Compare eso con el tipo basado sizeof en

int *****p = malloc(100 * sizeof(int ****));

Donde usted tiene también asegúrese de que ha utilizado el número correcto de * bajo sizeof.

Para cambiar a otro tipo solo tiene que cambiar un lugar (la declaración de p) en lugar de dos. Y las personas que tienen el hábito de lanzar el resultado de malloc tienen que cambiar tres lugares.

Más generalmente, tiene mucho sentido atenerse a la siguiente directriz: los nombres de tipo pertenecen a las declaraciones y a ningún otro lugar. Las declaraciones reales deben ser independientes del tipo. Deben evitar mencionar cualquier nombre de tipo o usar cualquier otra característica específica de tipo tanto como sea posible.

Esto último significa: Evitar moldes innecesarios. Evitar sintaxis de constantes innecesarias específicas de tipo (como 0.0 o 0L donde un simple 0 sería suficiente). Evite mencionar nombres de tipo bajo sizeof. Y así sucesivamente.

 60
Author: AnT,
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-23 17:22:11

Porque si en algún momento posterior p se hace para apuntar a otro tipo de estructura, entonces su sentencia de asignación de memoria usando malloc no tiene que cambiar, todavía asigna suficiente memoria requerida para el nuevo tipo . Asegura:

  • No tiene que modificar la instrucción de asignación de memoria cada vez que cambie el tipo para el que asigna memoria.
  • Su código es más robusto y menos propenso a errores manuales.

En general es siempre es una buena práctica no confiar en tipos concretos y la primera forma solo hace eso, no codifica un tipo.

 19
Author: Alok Save,
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-23 07:57:30

Es conveniente, porque puedes convertir esto:

struct node *p= malloc(sizeof(*p));

En esto:

#define MALLOC(ptr)   (ptr) = malloc(sizeof(*(ptr) ))

struct node *p;
MALLOC(p);

O, para una matriz:

#define MALLOC_ARR(ptr, arrsize) \
       (ptr) = malloc(sizeof(*(ptr) ) * arrsize)

struct node *p;
MALLOC_ARR(p, 20);

¿Y por qué esto es seguro? Porque el usuario que usa estas macros sería menos propenso a cometer errores que fueron delineados por AndreyT, al igual que en el caso de DIM() para obtener el tamaño de una matriz estática.

#define DIM(arr)   ((sizeof(arr))/(sizeof(arr[0])))

Esto también es más seguro, porque el usuario no necesita hacer que el tamaño de la matriz estática sea consistente en varios lugares. Establecer el tamaño de la matriz en un lugar y a continuación, solo tiene que utilizar el DIM() y ya está! El compilador se encarga de ello por ti.

 3
Author: ruben2020,
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-12-06 08:29:15

No afecta directamente a la seguridad, pero se puede afirmar que puede evitar un error en futuras revisiones. Por otro lado es fácil olvidar ese pequeño *. ¿Qué tal si lo convierte en un tipo, sin duda es más limpio.

typedef struct node
{
     int a;
     struct node * next;
} node_t;

Entonces puedes hacer esto:

node_t *p = malloc(sizeof(node_t));
 0
Author: dashesy,
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
2015-01-08 02:24:47