Pregunta

Estoy implementando un algoritmo polinomial de división y conquistar para poder compararlo con una implementación de OpenCl, pero no puedo obtener malloc trabajar. Cuando ejecuto el programa, asigna un montón de cosas, verifica algunas cosas y luego envía el size/2 al algoritmo. Entonces cuando golpeé el malloc Línea de nuevo, escupe esto:

malloc.c: 3096: sysmalloc: aserción `(old_top == ((((mbinPtr) (((char *) & ((av) -> bins [((1) - 1) * 2])) - __builtin_offsetof (struct (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 (sizeOf (size (size_t))) - 1))) && ((Old_top) -> size & 0x1) && ((unsigned long) Old_end & pagemask) == 0) 'Falló. 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);
}

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

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

¿Fue útil?

Solución

99.9% probable que haya corrompido la memoria (un buffer de flujo superior o inferior, escribió a un puntero después de que fue liberado, llamado gratis dos veces en el mismo puntero, etc.)

Ejecute su código en Valgrind Para ver dónde su programa hizo algo incorrecto.

Otros consejos

Para darle una mejor comprensión de por qué Esto sucede, me gustaría ampliar un poco la respuesta de @R-Samuel-Klatchko.

Cuando usted llama malloc, lo que realmente está sucediendo es un poco más complicado que solo darle una parte de la memoria para jugar. Bajo el capó, malloc También mantiene alguna información de limpieza sobre la memoria que le ha dado (lo más importante, su tamaño), de modo que cuando llame free, sabe cosas como la cantidad de memoria gratis. Esta información se mantiene comúnmente justo antes de que la ubicación de la memoria le devuelva malloc. Se puede encontrar información más exhaustiva en Internet ™, pero la (muy) idea básica es algo como esto:

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

Basándose en esto (y simplificando las cosas enormemente), cuando llamas malloc, necesita obtener un puntero a la siguiente parte de la memoria disponible. Una forma muy sencilla de hacer esto es mirar la memoria anterior que regaló y moverse size bytes más abajo (o arriba) en la memoria. Con esta implementación, termina con su memoria parecida de esta cosa después de asignar p1, p2 y p3:

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

Entonces, ¿qué está causando 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 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 para p2 que comienza a sobrescribir lo que hay en p3's size campo. Cuando ahora la próxima llamada malloc, analizará la última ubicación de memoria que regresó, mire su campo de tamaño, se mueva a p3 + size y luego comience a asignar memoria desde allí. Ya que su código se ha sobrescrito size, sin embargo, esta ubicación de memoria ya no es después de la memoria previamente asignada.

¡No hace falta decir que esto puede destruir estragos! Los implementadores de malloc Por lo tanto, han puesto una serie de "afirmaciones", o cheques, que intentan hacer un montón de cordura verificando esto (y otros problemas) si están a punto de suceder. En su caso particular, se violan estas afirmaciones 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, esta es una simplificación excesiva bruta, 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 cubrirlo todo en una respuesta para SO. ¡Esperemos que esto le haya dado un poco de vista de lo que realmente está causando el problema!

Mi solución alternativa para usar Valgrind:

Estoy muy feliz porque solo ayudé a mi amigo a depurar un programa. Su programa tenía este problema exacto (malloc() causando abortar), con el mismo mensaje de error de GDB.

Compilé su programa usando Desinfectante de dirección con

gcc -Wall -g3 -fsanitize=address -o new new.c
              ^^^^^^^^^^^^^^^^^^

Y luego corrió gdb new. Cuando el programa finaliza por SIGABRT causado en un posterior malloc(), se imprime mucha información útil:

=================================================================
==407==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6060000000b4 at pc 0x7ffffe49ed1a bp 0x7ffffffedc20 sp 0x7ffffffed3c8
WRITE of size 104 at 0x6060000000b4 thread T0
    #0 0x7ffffe49ed19  (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x5ed19)
    #1 0x8001dab in CreatHT2 /home/wsl/Desktop/hash/new.c:59
    #2 0x80031cf in main /home/wsl/Desktop/hash/new.c:209
    #3 0x7ffffe061b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
    #4 0x8001679 in _start (/mnt/d/Desktop/hash/new+0x1679)

0x6060000000b4 is located 0 bytes to the right of 52-byte region [0x606000000080,0x6060000000b4)
allocated by thread T0 here:
    #0 0x7ffffe51eb50 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb50)
    #1 0x8001d56 in CreatHT2 /home/wsl/Desktop/hash/new.c:55
    #2 0x80031cf in main /home/wsl/Desktop/hash/new.c:209
    #3 0x7ffffe061b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)

Echemos un vistazo a la salida, especialmente el rastro de la pila:

La primera parte dice que hay una operación de escritura no válida en new.c:59. Esa línea lee

memset(len,0,sizeof(int*)*p);
             ^^^^^^^^^^^^

La segunda parte dice que el recuerdo en el que se creó la mala escritura se crea en new.c:55. Esa línea lee

if(!(len=(int*)malloc(sizeof(int)*p))){
                      ^^^^^^^^^^^

Eso es todo. Solo me tomó menos de medio minuto localizar el error que confundió a mi amigo durante unas horas. Se las arregló para localizar el fracaso, pero es un posterior malloc() Llame a eso falló, sin poder detectar este error en el código anterior.

Resumen: prueba el -fsanitize=address de GCC o Clang. Puede ser muy útil al depurar problemas de memoria.

Probablemente estés invadiendo más allá del MEM asignado en alguna parte. Entonces el SW subyacente no lo recoge hasta que llames a Malloc

Puede haber un valor de guardia golpeado que está siendo atrapado por Malloc.

Editar ... Se agregó esto para la ayuda de verificación de límites

http://www.lrde.epita.fr/~akim/ccmp/doc/bounds-chetking.html

Recibí el siguiente mensaje, similar al 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.

Cometió un error a la llamada de método antes, cuando se usa Malloc. Sobrescribir erróneamente el signo de multiplicación '*' con un '+', al actualizar el factor después de sizeof ()-Operador al agregar un campo a una matriz de char sin firmar.

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, usé Malloc nuevamente y produjo el mensaje de error que se muestra arriba. La llamada fue (bastante simple):

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

Piense en usar el '+'-firmado en la primera llamada, que conduce a un mal culto en combinación con la inicialización inmediata de la matriz después de (la memoria de sobrescritura 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.

Recibimos este error porque olvidamos multiplicar por sizeof (int). Tenga en cuenta que el argumento a Malloc (..) es una serie de bytes, no un número de palabras de máquina o lo que sea.

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

Malloc.C: 3096: Sysmalloc: Afirmación usando 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 el propio LIBC.

Obtuve el mismo problema, usé Malloc sobre N sobre un bucle para agregar nuevos datos de cadena Char *. Me enfrenté al mismo problema, pero después de lanzar la memoria asignada void free() el problema fue ordenado

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top