¿Por qué obtengo un fallo en la aserción C malloc?


Estoy implementando un algoritmo polinómico divide y vencerás para que pueda compararlo con una implementación OpenCL, pero no puedo hacer que malloc funcione. Cuando corro el programa, asigna un montón de cosas, comprueba algunas cosas, luego envía el size/2 al algoritmo. Entonces cuando golpeo la línea malloc de nuevo escupe esto:

Malloc.c: 3096: SysMAlloc: Assertion ' (old_top = =((mbinptr) (((char*) &((av)->bins[((1) - 1) * 2])) - __builtin _ offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 1))) && ((old_top)->talla & 0x1) && ((unsigned long)old_end & pagemask) == 0)'no se pudo. Abortado

La línea en cuestión es:

int *mult(int size, int *a, int *b) {
    int *out,i, j, *tmp1, *tmp2, *tmp3, *tmpa1, *tmpa2, *tmpb1, *tmpb2,d, *res1, *res2;
    fprintf(stdout, "size: %d\n", size);

    out = (int *)malloc(sizeof(int) * size * 2);
}

Comprobé el tamaño con un fprintf, y es un entero positivo (generalmente 50 en ese punto). Intenté llamar malloc con un número llano también y todavía consigo el error. Estoy perplejo ante lo que está pasando, y nada de Google que haya encontrado hasta ahora es útil.

¿Alguna idea de lo que está pasando? Estoy tratando de averiguar cómo compilar un nuevo GCC en caso de que sea un error del compilador, pero realmente lo dudo.

Author: P Shved, 2010-06-07

7 answers

99.9% de probabilidad de que haya dañado la memoria (sobre - o bajo-fluyó un búfer, escribió a un puntero después de que fue liberado, llamado libre dos veces en el mismo puntero, etc.)

Ejecute su código bajo Valgrind para ver dónde su programa hizo algo incorrecto.

 71
Author: R Samuel Klatchko,
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-06-07 05:20:19

Para darles una mejor comprensión de por qué esto sucede, me gustaría ampliar un poco la respuesta de @r-samuel-klatchko.

Cuando llamas a malloc, lo que realmente está sucediendo es un poco más complicado que solo darte un pedazo de memoria para jugar. Bajo el capó, malloc también guarda alguna información de mantenimiento sobre la memoria que le ha dado (lo más importante, su tamaño), de modo que cuando llame a free, sabe cosas como cuánta memoria liberar. Esta información es normalmente se mantiene justo antes de que malloc le devuelva la ubicación de la memoria. Se puede encontrar información más exhaustiva en internet™, pero la idea (muy) básica es algo como esto:

+------+-------------------------------------------------+
+ size |                  malloc'd memory                +
+------+-------------------------------------------------+
       ^-- location in pointer returned by malloc

Basándose en esto (y simplificando mucho las cosas), cuando llamas a malloc, necesita obtener un puntero a la siguiente parte de la memoria que está disponible. Una forma muy simple de hacer esto es mirar el bit de memoria anterior que regaló, y mover size bytes más abajo (o arriba) en memoria. Con esta implementación, terminas con tu memoria mirando algo como esto después de asignar p1, p2 y p3:

+------+----------------+------+--------------------+------+----------+
+ size |                | size |                    | size |          +
+------+----------------+------+--------------------+------+----------+
       ^- p1                   ^- p2                       ^- p3

Entonces, ¿qué está causando tu error?

Bueno, imagine que su código escribe erróneamente más allá de la cantidad de memoria que ha asignado (ya sea porque asignó menos de lo que necesitaba como era su problema o porque está utilizando las condiciones de límite incorrectas en algún lugar de su código). Digamos que su código escribe tantos datos a p2 que se inicia sobrescribir lo que está en el campo p3 size. La próxima vez que llame a malloc, mirará la última ubicación de memoria que devolvió, mirará su campo de tamaño, se moverá a p3 + size y luego comenzará a asignar memoria desde allí. Sin embargo, dado que su código ha sobrescrito size, esta ubicación de memoria ya no está después de la memoria asignada anteriormente.

No hace falta decir que esto puede causar estragos! Los implementadores de malloc, por lo tanto, han puesto en una serie de "aserciones", o comprobaciones, que tratan de hacer un montón de comprobación de cordura para detectar esto (y otros problemas) si están a punto de suceder. En su caso particular, estas afirmaciones son violadas, y por lo tanto malloc aborta, diciéndole que su código estaba a punto de hacer algo que realmente no debería estar haciendo.

Como se dijo anteriormente, esto es una simplificación excesiva, pero es suficiente para ilustrar el punto. La implementación de glibc de malloc es más de 5k líneas, y ha habido cantidades sustanciales de investigación sobre cómo construir una buena dinámica mecanismos de asignación de memoria, por lo que cubrir todo en una respuesta SO no es posible. Esperemos que esto le ha dado un poco de una visión de lo que realmente está causando el problema sin embargo!

 48
Author: Jon Gjengset,
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-10-14 17:41:38

Probablemente esté sobrepasando el mem asignado en algún lugar. entonces el sw subyacente no lo capta hasta que llame a malloc

Puede haber un valor de guardia clobbered que está siendo capturado por malloc.

Editar...se agregó esto para la ayuda de comprobación de límites

Http://www.lrde.epita.fr / ~akim/ccmp/doc/bounds-checking.html

 2
Author: pbernatchez,
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-06-07 06:37:42

Recibí el siguiente mensaje, similar al tuyo:


    program: malloc.c:2372: sysmalloc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 *(sizeof(size_t))) - 1)) & ~((2 *(sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long) old_end & pagemask) == 0)' failed.

Cometió un error alguna llamada de método antes, al usar malloc. Erróneamente sobrescribió el signo de multiplicación ' * 'con un'+', al actualizar el factor después del operador sizeof () al agregar un campo a unsigned char array.

Aquí está el código responsable del error en mi caso:


    UCHAR* b=(UCHAR*)malloc(sizeof(UCHAR)+5);
    b[INTBITS]=(some calculation);
    b[BUFSPC]=(some calculation);
    b[BUFOVR]=(some calculation);
    b[BUFMEM]=(some calculation);
    b[MATCHBITS]=(some calculation);

En otro método más tarde, utilicé malloc de nuevo y produjo el mensaje de error que se muestra arriba. La llamada fue (simple suficiente):


    UCHAR* b=(UCHAR*)malloc(sizeof(UCHAR)*50);

Piense que el uso del signo '+'en la primera llamada, que conduce a un mal cálculo en combinación con la inicialización inmediata de la matriz después (sobrescribir la memoria que no se asignó a la matriz), trajo cierta confusión al mapa de memoria de malloc. Por lo tanto, la segunda llamada salió mal.

 2
Author: Michael Grieswald,
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
2016-10-31 15:05:36

Tenemos este error porque nos olvidamos de multiplicar por sizeof(int). Observe el argumento de malloc(..) es un número de bytes, no número de palabras máquina o lo que sea.

 1
Author: Phob,
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
2011-05-02 23:42:36

Estaba portando una aplicación de Visual C a gcc sobre Linux y tuve el mismo problema con

Malloc.c: 3096: SysMAlloc: Aserción usando gcc en UBUNTU 11.

He movido el mismo código a una distribución de Suse (en otro equipo ) y no tengo ningún problema.

Sospecho que los problemas no están en nuestros programas sino en el propio libc.

 0
Author: JMH,
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
2012-10-26 08:50:38

Tengo el mismo problema, usé malloc sobre n otra vez en un bucle para agregar nuevos datos de cadena char*. me enfrenté al mismo problema, pero después de liberar la memoria asignadavoid free() problema fueron ordenados

 0
Author: namila007,
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
2017-04-26 17:53:34