¿Qué es un glibc free / malloc / realloc invalid next / error de puntero no válido y cómo solucionarlo?

Probablemente esté viendo esta pregunta porque su pregunta se ha cerrado como un duplicado de esto. Para obtener una lista moderadamente completa de preguntas relacionadas, consulte Una larga lista de posibles duplicados: asignación de memoria C y límites de desbordamiento en Meta Stack Overflow.


Pregunta de ejemplo

De la char gratis *: el siguiente tamaño no válido (rápido) preguntado por noobie en 2014-04-11.

Estoy liberando un char* después de un proceso de concatenación, pero recibo este error:

 free(): invalid next size (fast): 0x0000000001b86170 

Este es mi código:

 void concat(stringList *list) { char *res = (char*)malloc(sizeof(char*)); strcpy(res, list->head->string); list->tmp = list->head->next; while (list->tmp != NULL) { strcat(res, ","); strcat(res, list->tmp->string); list->tmp = list->tmp->next; } printf("%s\n", res); free(res); } 

Pregunta genérica

Cuando ejecuto mi progtwig, veo un mensaje de error como este:

 *** glibc detected *** ./a.out: free(): corrupted unsorted chunks: 0x12345678 *** 

La información detallada puede contener cualquiera de los siguientes después de que *** glibc detected *** y el nombre del progtwig, y ​​el mensaje es seguido por una dirección hexadecimal (que se muestra como 0x12345678) y otro *** :

  • free(): corrupted unsorted chunks: 0x12345678
  • free(): invalid next size (fast): 0x12345678
  • free(): invalid next size (normal): 0x12345678
  • free(): invalid pointer: 0x12345678
  • free(): invalid size: 0x12345678
  • malloc(): corrupted unsorted chunks: 0x12345678
  • malloc(): corrupted unsorted chunks 2: 0x12345678
  • malloc(): memory corruption: 0x12345678
  • malloc(): memory corruption (fast): 0x12345678
  • malloc(): smallbin double linked list corrupted: 0x12345678
  • munmap_chunk(): invalid pointer: 0x12345678
  • realloc(): invalid next size (fast): 0x12345678
  • realloc(): invalid old size (fast): 0x12345678
  • realloc(): invalid pointer: 0x12345678
  • corrupted double-linked list: 0x12345678

Esto ocurre al llamar a la función frobnicate() ; ¿Qué pasa con esa función?

Respuesta para una pregunta de ejemplo

unwind dio la respuesta aceptada a la pregunta de ejemplo:

Tu código es incorrecto

Está asignando espacio para un único puntero ( malloc(sizeof(char*)) ), pero no caracteres. Está sobrescribiendo el espacio asignado con todas las cadenas, lo que provoca un comportamiento indefinido (en este caso particular, corrompe los datos de contabilidad de malloc() ).

No necesita asignar espacio para el puntero ( res ); es una variable local. Debe asignar espacio para todos los caracteres que desea almacenar en la dirección que contiene el puntero.

Como va a recorrer una lista para buscar cadenas para concatenar, no puede saber el tamaño total por adelantado. Tendrás que hacer dos pasadas sobre la lista: una para sumr el strlen() de cada cadena, luego asignar ese espacio más para el separador y el terminador, luego otro pase cuando realices la concatenación.

Respuesta genérica

Lo que está viendo es el resultado de una corrupción en las estructuras internas del asignador glibc. Cuando asigna o libera memoria dinámica, el asignador debe administrar la memoria que reserva del sistema operativo y, dependiendo de la acción solicitada por usted, encontrar un nuevo fragmento para distribuir, ordenar un fragmento liberado en la lista de aquellos que puede distribuir más tarde nuevamente, o devolver la memoria al sistema operativo. Estos mensajes de error muestran que las estructuras de datos que utiliza para administrar esta funcionalidad están dañadas.

Todos estos errores significan que parte de su código tiene memoria modificada que no se le dio para usar, invocando un comportamiento indefinido . Esto es muy probablemente el resultado de sobreescribir algo de memoria bastante antes en su progtwig, y ​​es totalmente posible que el error no se encuentre en la función frobnicate() .

Sí, esto significa que el error puede estar en cualquier parte de tu progtwig o de las bibliotecas de terceros que uses .

Probablemente esta no sea una buena pregunta para Stack Overflow. A menos que tenga una buena reproducción simple de su problema, esta comunidad puede ser incapaz de ayudarlo mucho. La causa del error puede estar en cualquier parte de su código (y muy a menudo no está en la función donde se detecta el error), y puede estar en un código que no podemos ver. Stack Overflow no es un sitio de depuración colaborativa. Incluso cuando alguien puede encontrar el defecto en su código, es poco probable que su pregunta específica pueda ayudar a un futuro visitante.

Causas comunes

  • Use después de forma gratuita. Ha liberado / eliminado algo de memoria y escrito en ella después, sobrescribiendo las estructuras que glibc necesita para la contabilidad.
  • Off-by-N error. Está escribiendo N bytes después de un fragmento asignado en la memoria no asignada que glibc usa internamente para su contabilidad.
  • Punteros no inicializados. No estás inicializando un puntero. Por coincidencia, apunta a cierta memoria reservada por glibc pero no asignada por su progtwig y usted escribe en ella.
  • Asignando la cantidad incorrecta de espacio. Esto puede deberse a que escribió long *data = malloc(number * 4) lugar de long *data = malloc(number * sizeof(long)); o (mejor) long *data = malloc(number * sizeof(*data)); . Hay muchas otras maneras de hacer mal el cálculo del tamaño. Otra común es olvidarse de dar cuenta del carácter terminador nulo al final de una cadena: char *copy = malloc(strlen(str)); en lugar de char *copy = malloc(strlen(str)+1); .

Lo que tienes que hacer ahora es arremangarte y solucionar el problema

No hay una respuesta simple qué buscar o qué arreglar. Ninguna construcción sintáctica única que estaba utilizando mal. La causa de este error puede venir literalmente en miles de variedades.

Herramientas

  • valgrind Una herramienta creada principalmente con el propósito de encontrar exactamente este tipo de errores. Si no puede encontrar nada, asegúrese de estar utilizando la última versión, y también está probando la herramienta exp-sgcheck incluida. Si está ejecutando código multiproceso, la causa también podría estar relacionada con una condición de carrera, por lo que es posible que desee probar las drd condición de carrera incluidas drd y helgrind para obtener más información. En el momento de escribir esto, valgrind admite las siguientes plataformas:
    • X86 / Linux,
    • AMD64 / Linux,
    • ARM / Linux,
    • PPC32 / Linux,
    • PPC64 / Linux,
    • S390X / Linux,
    • MIPS32 / Linux,
    • MIPS64 / Linux,
    • ARM / Android (2.3.x y posterior),
    • X86 / Android (4.0 y posterior),
    • X86 / Darwin y
    • AMD64 / Darwin (Mac OS X 10.7, con soporte limitado para 10.8).
  • purificar Una herramienta similar a valgrind, pero comercial y dirigida a un conjunto diferente de plataformas.
  • AddressSanitizer Una herramienta similar, pero integrada en la cadena de herramientas del comstackdor (gcc y clang).
  • efence Una caída en el reemplazo del asignador que intentará bloquear su progtwig antes, para que pueda averiguarlo con un depurador normal donde ocurrió la escritura en la memoria no válida.
  • dmalloc una biblioteca con un propósito similar a efence.

Necesitando más asistencia

Si no puede resolver su problema utilizando una de estas herramientas, debe intentar crear un MCVE ( ¿Cómo crear un ejemplo mínimo, completo y verificable? ) O, de manera equivalente, un SSCCE ( Corto, autónomo, correcto (comstackble) , Ejemplo ).

Recuerde trabajar en una copia de su código porque la creación de un MCVE requiere que elimine despiadadamente el código que no ayuda a reproducir el problema. Usar una VCS (sistema de control de versiones) para ayudar es una buena idea; puede registrar etapas intermedias para reducir el problema a un mínimo. Puede ser un nuevo repository descartable solo para reducir su problema a un tamaño manejable.

Con un buen diseño modular para su código, debería ser relativamente fácil crear el MCVE. Quizás también ya tenga una prueba unitaria que sea más adecuada para alimentar una de las herramientas anteriores. También es posible que desee crear uno que luego sirva como una prueba de regresión para este error.