2010-06-07 22 views
54

Estoy implementando un algoritmo polinomial de división y conquista para poder compararlo con una implementación de OpenCL, pero no puedo hacer que malloc funcione. Cuando ejecuto el programa, asigna un montón de cosas, comprueba algunas cosas y luego envía el size/2 al algoritmo. Luego, cuando llegué a la línea malloc nuevo escupe esto:¿Por qué obtengo una falla de aserción C malloc?

malloc.c: 3096: sYSMALLOc: `aserción (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) -> tamaño & 0x1) & & ((unsigned long) old_end & pagemask) == 0)' fracasado. Aborted

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); 
} 

I comprobado tamaño con una fprintf, y es un número entero positivo (por lo general 50 en ese punto). Traté de llamar al malloc con un número simple también y sigo recibiendo el error. Estoy perplejo por lo que está pasando, y nada de Google que he encontrado hasta ahora es útil.

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

+0

sospecho que el problema es en realidad una línea anterior a esa. Tal vez un doble gratis? –

+0

tercera línea en el programa: int * mult (tamaño int, int * a, int * b) { \t int * a cabo, i, j, * tmp1, * TMP2, * tmp3, * tmpa1 , * tmpa2, * tmpb1, * tmpb2, d, * res1, * res2; \t fprintf (stdout, "size:% d \ n", size); \t \t out = (int *) malloc (sizeof (int) * size * 2); – Chris

Respuesta

65

99,9% de probabilidades de memoria que ha corrompido (sobre o sub-fluía un tampón, escribió a un puntero después de haber sido liberado, llamada gratuita dos veces en el mismo puntero, etc.)

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

+1

fijo. Valgrind definitivamente ayudó. Transcribí mal mi antiguo código matlab y tuve un bucle for que iteraba sobre j, luego dentro j ++, que sobreescribía la matriz en la que estaba escribiendo y de alguna forma causaba que fallara malloc. gracias por la ayuda! – Chris

+0

Valgrind era solo la herramienta que necesitaba para descubrir qué estaba pasando cuando recibí este error. Gracias por mencionarlo. – alexwells

+1

Hice la compilación limpia y funcionó correctamente. –

1

Conseguimos este error, ya que se olvidó de multiplicar por sizeof (int). Tenga en cuenta que el argumento para malloc (..) es un número de bytes, no el número de palabras de máquina o lo que sea.

0

me portar una aplicación de Visual C gcc sobre Linux y que tenía el mismo problema con

malloc.c: 3096: sYSMALLOc: aserción utilizando gcc en UBUNTU 11.

Moví el mismo código a una distribución de Suse (en otra computadora) y no tengo ningún problema.

Sospecho que los problemas no están en nuestros programas sino en la propia libc.

40

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

Cuando llama al malloc, lo que realmente está sucediendo es un poco más complicado que solo darle un pedazo de memoria para jugar. Debajo del capó, malloc también guarda algo de información sobre la memoria que le ha dado (más importante, su tamaño), de modo que cuando llame al free, sepa cosas como la cantidad de memoria para liberar. Esta información normalmente se conserva justo antes de que la ubicación de la memoria le sea devuelta por malloc. una información más detallada se puede encontrar on the internet™, pero el (muy) idea 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 se llama malloc, que necesita para 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 la memoria. Con esta aplicación, usted termina con su memoria buscando algo como esto después de asignar p1, p2 y p3:

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

Por lo tanto, la causa de su 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 ya que era su problema o porque está utilizando las condiciones de frontera incorrectas en algún lugar de su código). Supongamos que su código escribe tantos datos en p2 que comienza a sobrescribir lo que está en el campo p3size. Cuando vuelva a llamar al malloc, verá la última ubicación de memoria que devolvió, mire su campo de tamaño, vaya al p3 + size y luego comience 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 previamente asignada.

Huelga decir que esto puede causar estragos. Los implementadores de malloc han incluido una serie de "aseveraciones", o comprobaciones, que intentan hacer un montón de chequeos de cordura para detectar esto (y otros problemas) si están por 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 buenos mecanismos de asignación de memoria dinámica, por lo que no es posible cubrir todo en una respuesta SO. Sin embargo, afortunadamente, esto te ha dado una idea de lo que realmente está causando el problema.

+0

Esta debería ser la respuesta aceptada .. –

1

me dieron el siguiente mensaje, similar a uno:

 

    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. 

cometido un error alguna llamada al método anterior, cuando se utiliza malloc. Erróneamente sobrescribió el signo de multiplicación '*' con un '+', al actualizar el factor después de sizeof() - operador al agregar un campo a una matriz de caracteres sin signo.

Este es 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, solía malloc nuevo y se produjo el mensaje de error mostrado anteriormente. La llamada era (bastante simple):

 

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

Piense usando los botones '+' - letrero en la primera llamada, que conducen a errores de cálculo en combinación con la inicialización inmediata de la matriz después (memoria de sobrescribir que no era asignado a la matriz), trajo un poco de confusión al mapa de memoria de malloc. Por lo tanto, la segunda llamada salió mal.

0

tengo el mismo problema, utilicé malloc sobre n una vez más en un bucle para agregar nuevos datos de cadena de caracteres *. me enfrenté al mismo problema, pero después de liberar la memoria asignada se resolvió el problema void free()

Cuestiones relacionadas