Error SIGABRT en __kernal_vsyscall al llamar a malloc

Agrupa todas las consultas sobre los lenguajes de programacion como C, C++, Python, Java ...

Error SIGABRT en __kernal_vsyscall al llamar a malloc

Notapor lacabra25 » Jue Dic 24, 2009 12:14 pm

Hola, me acabo de encontrar con una señal de error que nunca antes habia visto, y la primera vez que me encuentro con que malloc en lugar de devolver NULL en caso de no poder reservar la memoria me de este error. En una linea de un programa en C donde uso malloc para reservar memoria para poder duplicar una cadena de caracteres y trabajar con la copia sin modificar la original, al llamar a la funcion malloc es donde el programa aborta mostrando en el debugger "Program received signal SIGABRT, Aborted." y debajo de eso "0xb8082430 in __kernel_vsyscall ()".
Ya comprobe con el debugger que es justo en la linea donde uso malloc para reservar la memoria para una cadena de caracteres donde da ese error, pero no se a que puede ser debido ni como solucionarlo.
Código: Seleccionar todo
char *texto2;
texto2 = (char *) malloc (sizeof (char) * (caracteres + 1));

caracteres es una variable tipo unsigned long int que contiene la longitud de la cadena a copiar obtenida por strlen (y sumo uno para poder contener tambien el caracter nulo ademas de cada uno de los caracteres).
Avatar de Usuario
lacabra25
 
Mensajes: 222
Registrado: Mié Abr 02, 2008 9:45 pm
Ubicación: Tenerife (España)

Notapor Geo » Jue Dic 24, 2009 5:28 pm

Probando el código no me arroja ningún problema, ¿hay alguna condición en específico que lo cause, con qué compilador trabajas?
La imaginación es el límite.
Visita mi blog en inglés o en español.
Geo
 
Mensajes: 244
Registrado: Jue Ago 10, 2006 3:51 am
Ubicación: México

Notapor lacabra25 » Jue Dic 24, 2009 7:27 pm

No hay ninguna condicion, por lo menos que conozca, especial que cause esto y buscando por google lo unico que encuentro son paginas para aprovechar desbordamientos de buffer o que los explican, pero nada util para esta situacion. Lo raro es que no funciona ninguna llamada a malloc del codigo sino solo una serie de llamadas que con GDB he visto que realiza el programa al comienzo de todo (antes de la primera instruccion en main), de resto ninguna llamada a malloc funciona, y da siempre este error. Y aun más raro es que este error no lo daba antes, despues de añadir una funcion que (aunque usa malloc para reservar memoria) no tiene nada que ver con ninguna otra de las que usan malloc, fue entonces cuando empezo a dar este error, pero no entiendo que error puede producirse al reservar memoria aparte de que devuelva NULL.
Uso el compilador GCC, uso GNU/Linux Trisquel, de depurador GDB. He probado a, mediante una instruccion de GDB sugerida por el mismo al llegar a este error en el primer malloc, a hacer que ignore esta señal y continue la ejecucion, y ignorando la señal funciona el programa sin problemas hasta llegar al siguiente malloc donde da el mismo error.
Segun he podido encontrar por google SIGABRT es una señal para abortar la ejecucion, que se supone que es para cuando no se puede continuar la ejecucion correctamente pero aun se puede salir limpiamente sin provocar errores mayores y realizando un volcado de memoria de ser necesario, y la funcion __kernel_vsyscall al parecer por lo que he encontrado se encarga de comprobar que es mas rapido para realizar una llamada (ponian de ejemplo dos opciones que no recuerdo y int80, esta ultima tengo entendido que es la interrupcion del kernel). Lo que no entiendo es que tan grave problema puede producirse al intentar reservar memoria como para tener que abortar el sistema el programa, en lugar de no asignar memoria y devolverme un simple NULL.
Esta cuenta ahora a pasado a la cuenta jhg
Avatar de Usuario
lacabra25
 
Mensajes: 222
Registrado: Mié Abr 02, 2008 9:45 pm
Ubicación: Tenerife (España)

Notapor lacabra25 » Lun Ene 04, 2010 4:36 pm

He estado buscando más informacion, intentando descubrir que puede causar que una sencilla llamada a malloc falle dando una señal de abortar el programa, aunque no he conseguido solucionarlo aun, dejo la informacion que he podido obtener con el debugger y la que he encontrado por internet por si facilita que me puedan ayudar a resolver tan raro error.
Con el debugger he podido ver que aunque la señal SIGABRT (señal para abortar la ejecucion) se produce en una de las llamadas a la funcion __kernel_vsyscall, esta funcion es llamada sin problemas anteriormente tanto por la funcion malloc como al iniciarse el programa (antes incluso de la primera linea de codigo en la funcion main), antes de la llamada a dicha funcion que produce la señal para abortar la ejecucion, se produce una corrupcion de memoria en la funcion malloc justo despues de llamar 15 veces a la funcion __kernel_vsyscall (pero no se produce dentro de dicha funcion, sino en la funcion malloc justo despues de haber llamado y ejecutado por 15 vez dicha funcion, despues de la corrupcion de momoria malloc realiza otras 4 llamadas a esa funcion sin problemas y es a la 5 vez cuando dentro de dicha funcion se produce la señal de abortar la ejecucion.
Cuando el debugger indica la corrupcion de memoria indica una direccion de memoria que, en el volcado de memoria que muestra al producirse la señal de abortar la ejecucion se corresponde con una direccion de memoria perteneciente al heap, al producirse la señal SIGABRT ademas del volcado de memoria el debugger muestra una direccion de memoria, que en el volcado de memoria se corresponde con una zona de memoria perteneciente al vdso (el heap tengo entendido que es parte de la memoria que ocupa el programa al cargarse desde disco y que se dedica a las variables en C, corrijanme si me equivoco; y vdso no tengo ni idea de que es, francamente).
Con el debugger tambien he podido comprobar que al iniciarse la ejecucion, antes de llegar a la primera linea del codigo en C, se llama 18 veces a malloc (sin que de este problema ni ningun otro en ninguna de estas llamadas) y se llama 100 veces a __kernel_vsyscall sin contar con las veces que sea llamada dentro de las llamadas a malloc anteriores, todo esto sin producirse ningun error. Esto más que ayudarme a entender por donde puede estar el problema me deja igual o más desconcertado, ya que no entiendo que puede probocar que una funcion que funciona sin problemas durante el comienzo de la ejecucion de errores en otra parte de la ejecucion, en la que antes no daba error, y encima comienza a dar el error tras escribir otras funciones que nisiquiera son llamadas antes de que se produzca este error.
Sobre alguna condicion especial que lo provoque, que ya lo preguntaron anteriormente, no se me ocurre ninguna, no hay diferencia entre antes de este error y despues de este error, no he cambiado nada del ordenador, ni he cambiado la version del compilador ni de las bibliotecas, no se me ocurre ninguna condicion especial que pueda probocarlo. No se si tal vez se deba a algun tipo de ecepcion de la funcion malloc que aun no ha sido detectado por los mantenedores de las bibliotecas de C que usa GCC, y que por alguna razon que desconozco se hayan dado las circunstancias (que tambien desconozco) para que se produzca dicha excepcion, es lo unico que se me ocurre. ¿a alguien se le ocurre algo, o sabe algo?, ¿alguien sabe la web o el correo de los mantenedores de las bibliotecas de C que usa GCC para ver si ellos saben algo sobre este error?
Avatar de Usuario
lacabra25
 
Mensajes: 222
Registrado: Mié Abr 02, 2008 9:45 pm
Ubicación: Tenerife (España)

Notapor hugoruscitti » Lun Ene 04, 2010 6:23 pm

Saludos, yo tuve un problema muy similar en un programa
que utilizaba buffers con memoria dinámica.

En mi caso el problema se daba porque asignabamos memoria
para cadenas y luego escribíamos sobre esas cadenas saliendonos
de los límites. Un error que el compilador no verifica, el depurador
no verifica, y por supuesto, hacía el que el programa
aborte en cualquier momento mientras se ejecuta.

Por ejemplo, en nuestro programa, luego de sobrepasarnos de
un buffer, al llamar a malloc, calloc o printf (si, printf) el programa
daba un error horrible como ese que nos indicas.

Resulta que cuando el programa realiza una operación de lectura
y escritura, el sistema operativo toma el control y pasa cuentas
del error que cometimos con la memoria.

Si tu caso es similar al que se me presentó con mis amigos, lo
que podrías hacer es utilizar una herramienta como valgrind.
Este programa se ejecuta como simulador de tu sistema, y
emite un reporte completo de todos los detalles erroneos
en tiempo de ejecución, por ejemplo: variables utilizadas
antes de inicializar, salirse de un vector o no liberar memoria
reservada.

Te dejo un ejemplo:

Imagina que tengo este programa en el archivo test.c:

Código: Seleccionar todo
#include <stdio>

int main(void)
{
    int vector[2];
    int otro;

    printf("El valor de otro es: %d\n", otro);

    vector[0] = 0;
    vector[1] = 0;
    vector[2] = 0;

    return 0;
}


Este programa tiene dos errores, utilizo la variable 'otro'
sin inicializar, y luego escribo en una zona no permitida
de un vector (que solo tiene dos posiciones y yo escribo
en tres posiciones).

Para conocer con detalle los errores ejecuto valgrind:

Código: Seleccionar todo
valgrind ./test


y el resultado que obtengo me da un detalle de todos los
errores que podrían corromper la memoria. Problemas que
se originan en mi código, pero que se trasladan a la
biblioteca de C en donde pueden, literalmente, ¡explotar!:

Código: Seleccionar todo
....
==6748== Use of uninitialised value of size 4
==6748==    at 0x407C186: _itoa_word (_itoa.c:195)
==6748==    by 0x407FA81: vfprintf (vfprintf.c:1600)
==6748==    by 0x4086F7F: printf (printf.c:35)
==6748==    by 0x8048401: main (test.c:9)
==6748==
==6748== Conditional jump or move depends on uninitialised value(s)
==6748==    at 0x407C18E: _itoa_word (_itoa.c:195)
==6748==    by 0x407FA81: vfprintf (vfprintf.c:1600)
==6748==    by 0x4086F7F: printf (printf.c:35)
==6748==    by 0x8048401: main (test.c:9)
....



No se si tu problema se resolverá con la misma herramienta,
pero es bueno hacer la prueba. Si un programa tiene un
error, por mas sutil que sea, y corrompe las estructuras de
datos, el error puede originar un fallo dentro de la biblioteca
C. Ten en cuenta que aquí el error llegó hasta _itoa_word, que
ni se lo que significa...

Saludos.
Avatar de Usuario
hugoruscitti
Site Admin
 
Mensajes: 1242
Registrado: Dom Jul 30, 2006 3:57 am
Ubicación: Buenos Aires, Argentina

Notapor lacabra25 » Mar Ene 05, 2010 1:59 am

Hugo gracias, tomo nota de la herramienta que nombras y mañana (ahoramismo aqui en españa son las dos menos cuarto de la noche, y lo mejor que puedo hacer ahora es dormir) comienzo a revisar cualquier posible error que pueda llevar a un desbordamiento de buffer o que haga un mal uso de memoria y que pueda ser causante de la corrupcion de memoria que despues sale a la luz en la biblioteca de C produciendo la señal de abortar. Aunque como aun no he probado la herramienta (por como acabo de leer tu respuesta) y no he solucionado por tanto el error, ya por lo menos el tener algo que intentar y que pueda solucionar el problema me quita un gran peso de encima, aunque no se acaba el mundo por que programando el programa tenga un error se pasa bastante mal el solo saber que tipo de error es y que encima ese tipo de errores puede aparecer en una parte del programa pero originarse en cualquier otra, y encima cuando a uno le pasa esto por primera vez, es como ponerse a buscar un error a ciegas.
En cuanto pruebe mañana a solucionar el error os comento que tal fue y si consigo arreglarlo os comento que causaba este error (seguramente algun detalle tonto, y eso encima de haberme preocupado de usar strncpy y strncat en lugar de strcpy y strcat para evitar los desbordamientos de buffer). Gracias nuevamente.

Edito:
Consegui solucionar el problema al final, resulto ser curiosamente al usar una funcion strncpy, que estaba usando precisamente para evitar desbordamientos de buffer que provocaran errores, el problema estaba en que al indicar la longitud maxima que tiene la cadena donde se va a copiar la otra, un error al teclear el un simple numero que me ha tenido dias dando vueltas por el codigo hasta encontrarlo. Aunque la cadena que se copiaba no llevaba a la longitud real de la cadena, por lo que no tendria que haber habido desbordamiento de buffer, debe ser que completa el resto con caracteres nulos y eso produjo el desbordamiento.

Gracias hugo por la ayuda.
Esta cuenta ahora a pasado a la cuenta jhg
Avatar de Usuario
lacabra25
 
Mensajes: 222
Registrado: Mié Abr 02, 2008 9:45 pm
Ubicación: Tenerife (España)


Volver a Sobre lenguajes de programación

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado

cron