GNU/Linux >> Tutoriales Linux >  >> Linux

¿Qué devuelve malloc(0)?

Otros han respondido cómo malloc(0) obras. Responderé una de las preguntas que hiciste y que aún no ha sido respondida (creo). La pregunta es sobre realloc(malloc(0), 0) :

¿Qué significa malloc(0) ¿devolver? ¿La respuesta sería la misma para realloc(malloc(0),0)? ?

El estándar dice esto sobre realloc(ptr, size) :

  • si ptr es NULL , se comporta como malloc(size) ,
  • de lo contrario (ptr no es NULL ), desasigna el antiguo puntero de objeto por ptr y devuelve un puntero a un nuevo búfer asignado. Pero si size es 0, C89 dice que el efecto es equivalente a free(ptr) . Curiosamente, no puedo encontrar esa declaración en el borrador C99 (n1256 o n1336). En C89, el único valor sensato para devolver en ese caso sería NULL .

Entonces, hay dos casos:

  • malloc(0) devuelve NULL en una implementación. Entonces tu realloc() llamada es equivalente a realloc(NULL, 0) . Eso es equivalente a malloc(0) desde arriba (y eso es NULL en este caso).
  • malloc(0) devuelve no NULL . Entonces, la llamada es equivalente a free(malloc(0)) . En este caso, malloc(0) y realloc(malloc(0), 0) son no equivalente.

Tenga en cuenta que aquí hay un caso interesante:en el segundo caso, cuando malloc(0) devuelve no NULL en caso de éxito, aún puede devolver NULL para indicar el fracaso. Esto resultará en una llamada como:realloc(NULL, 0) , que sería equivalente a malloc(0) , que puede o no devolver NULL .

No estoy seguro si la omisión en C99 es un descuido o si significa que en C99, realloc(ptr, 0) para no NULL ptr no es equivalente a free(ptr) . Acabo de probar esto con gcc -std=c99 , y lo anterior es equivalente a free(ptr) .

Editar :Creo que entiendo cuál es tu confusión:

Veamos un fragmento de tu código de ejemplo:

ptr = malloc(0);
if (ptr == realloc(ptr, 1024))

Lo anterior no es lo mismo que malloc(0) == realloc(malloc(0), 1024) . En el segundo, el malloc() la llamada se realiza dos veces, mientras que en la primera, está pasando un puntero previamente asignado a realloc() .

Analicemos primero el primer código. Asumiendo malloc(0) no devuelve NULL en caso de éxito, ptr tiene un valor válido. Cuando haces realloc(ptr, 1024) , realloc() básicamente te da un nuevo búfer que tiene el tamaño 1024 y el ptr se vuelve inválido. Una implementación conforme puede devolver la misma dirección que la que ya está en ptr . Entonces, tu if la condición puede volver verdadera. (Tenga en cuenta, sin embargo, mirando el valor de ptr después de realloc(ptr, 1024) puede ser un comportamiento indefinido).

Ahora la pregunta que haces:malloc(0) == realloc(malloc(0), 1024) . En este caso, supongamos que tanto el malloc(0) en LHS y RHS devuelve no NULL . Entonces, están garantizados para ser diferentes. Además, el valor de retorno de malloc() en el LHS no ha sido free() d todavía, por lo que cualquier otro malloc() , calloc() o realloc() puede que no devuelva ese valor. Esto significa que si escribió su condición como:

if (malloc(0) == realloc(malloc(0), 1024)
    puts("possible");

no verás possible en la salida (a menos que ambos malloc() y realloc() falla y devuelve NULL ).

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    void *p1;
    void *p2;

    p1 = malloc(0);
    p2 = realloc(p1, 1024);
    if (p1 == p2)
        puts("possible, OK");

    /* Ignore the memory leaks */
    if (malloc(0) == realloc(malloc(0), 1024))
        puts("shouldn't happen, something is wrong");
    return 0;
}

En OS X, mi código no generó nada cuando lo ejecuté. En Linux, imprime possible, OK .


malloc(0) está definido para la implementación en lo que respecta a C99.

Desde C99 [Sección 7.20.3]

El orden y la contigüidad del almacenamiento asignado por llamadas sucesivas a las funciones calloc, malloc y realloc no están especificados . El puntero devuelto si la asignación tiene éxito se alinea adecuadamente para que pueda asignarse a un puntero a cualquier tipo de objeto y luego usarse para acceder a dicho objeto o una matriz de tales objetos en el espacio asignado (hasta que el espacio se desasigna explícitamente). El tiempo de vida de un objeto asignado se extiende desde la asignación hasta la desasignación. Cada asignación producirá un puntero a un objeto disjunto de cualquier otro objeto. El puntero devolvió puntos al inicio (la dirección de byte más baja) 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 está definido por 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.


En C89, malloc(0) depende de la implementación; no sé si C99 solucionó esto o no. En C++, usando:

char * p = new char[0];

está bien definido:obtiene un puntero válido, no nulo. Por supuesto, no puede usar el puntero para acceder a lo que apunta sin invocar un comportamiento indefinido.

En cuanto a por qué esto existe, es conveniente para algunos algoritmos y significa que no necesita ensuciar su código con pruebas para valores cero.


Linux
  1. ¿Qué significa "-" (doble guión)?

  2. ¿Qué hace “lc_all=c”?

  3. Que hace ?

  4. ¿Qué hace Exec 3?

  5. ¿Qué hace Bamfdaemon?

¿Qué hace realmente Libgl_always_indirect=1?

Que hace . ~/.bashrc Comando Hacer??

¿Qué significa 'cd -'?

¿Qué código de error devuelve un proceso que falla en el segmento?

¿Qué hace CAP_NET_RAW?

¿Qué hace echo $? ¿hacer?