• Domingo 15 de Diciembre de 2024, 04:10

Autor Tema:  Segmentation Fault...cual Es El Error?  (Leído 3745 veces)

JoseTlaseca

  • Nuevo Miembro
  • *
  • Mensajes: 9
    • Ver Perfil
Segmentation Fault...cual Es El Error?
« en: Miércoles 28 de Mayo de 2008, 18:46 »
0
Hola a todos.
Ojala y puedan ayudarme con un problema que tengo y no se como solucionarlo:

Estoy trabajando con imagenes digitales en c++ con qt y hay una parte de mi codigo que me marca violacion de segmento, lo unico que quiero hacer hasta ahora es guardar el promedio ponderado de los canales de una imagen en una matriz de pixeles... les explico (solo pongo las partes de codigo que se ven involucradas):

Tengo unas declaraciones asi:

//En un archivo .h
   //Matriz en la que se van a guardar los pixeles de la imagen original
    unsigned char **matrizImagen;

  //Apuntador al inicio de la imagen a pintar, para modificar los canales con el polinomio de direcc.
    unsigned char *pixelImagen;

int rowstride;


******************************

//en un archivo .cpp

//Reservar memoria para la matriz de pixeles

matrizImagen = new unsigned char*[imageAlto];
//imageAlto vale 480
for(int i=0 ; i < imageAlto ; i++)
        matrizImagen=new unsigned char[imageAncho];
//imageAncho vale 640


rowstride = imageImagen->bytesPerLine(); //bytesPerLine es parte de qt y devuelve un entero que es el num de bytes por linea en una imagen

pixelImagen = imageImagen->bits();
//en imageImagen hay una imagen de tipo QImage

//la parte donde llamo a la susodicha funcion es:
//guardo imagen original en matriz
llenarMatrizOriginal( imageAlto, imageAncho, pixelImagen, matrizImagen, rowstride );

*******************************

//El cuerpo de la funcion es el siguiente:

void seguimiento::llenarMatrizOriginal( int alto, int ancho, unsigned char *imagePixelPointer, unsigned char **matriz, int rowstride )
{
   float alpha, beta, gamma;
   alpha=0.2125;
   beta=0.7154;
   gamma=0.0721;
   unsigned char *indice;
   int R, G, B;

   unsigned char temp;
   
   for(int i=0; i<alto; i++)
   for(int j=0; j<ancho; j++)
          {
      indice = imagePixelPointer + (i* rowstride) + (j * 4);
      B = (*indice); indice++;
      G = (*indice); indice++;
      R = (*indice);
                //LA SIGUIENTE ES LA LINEA QUE ME DA PROBLEMAS
                //LO SE PORQUE SI LA PONGO COMO COMENTARIO NO ME
                // DA EL ERROR DE VIOLACION DE SEGMENTO
      matriz[j] = (unsigned char)(alpha*( R)+beta*( G)+gamma*( B ));
          }
}


//por ultimo en el destructor de la clase libero la memoria de la matriz:

    for(int x=0; x< imageAlto; x++)
        delete[] matrizImagen
  • ;

   
    delete[] matrizImagen;
    matrizImagen=NULL;


*************************

Si cambio en la asignacion matriz[j] por alguna otra variables, por ejemplo un entero, como a continuacion:

temp = (unsigned char)(alpha*( R)+beta*( G)+gamma*( B ));//temp de tipo int

ya no me da el error... en resumen el problema esta en esa asignacion... pero yo no lo veo....

Alguno me puede ayudar?

Eternal Idol

  • Moderador
  • ******
  • Mensajes: 4696
  • Nacionalidad: ar
    • Ver Perfil
Re: Segmentation Fault...cual Es El Error?
« Respuesta #1 en: Miércoles 28 de Mayo de 2008, 19:07 »
0
Depuralo, fijate que valores tienen matriz, i y j.

Nacional y Popular En mi país la bandera de Eva es inmortal.


Queremos una Argentina socialmente justa, económicamente libre y  políticamente soberana.
¡Perón cumple, Evita dignifica!


La mano invisible del mercado me robo la billetera.

JoseTlaseca

  • Nuevo Miembro
  • *
  • Mensajes: 9
    • Ver Perfil
Re: Segmentation Fault...cual Es El Error?
« Respuesta #2 en: Miércoles 28 de Mayo de 2008, 21:35 »
0
He hecho algunas pruebas y creo que el problema no está en los indices ni en el tamaño de la matriz como yo habia pensado... he comprobado que los indices i y j siempre se comportan 0<i<480 y 0<j<640.  Respecto al tamaño de la matriz corregí su tamaño (que no me solucionó el problema, pero estaba mal) de la siguiente forma:

   //Reservar memoria para la matriz de pixeles
   matrizImagen = new unsigned char*[imageAlto];
       for(int i=0 ; i < imageAlto ; i++)
           matrizImagen=new unsigned char[imageAncho];

Lo unico que hice fué dejar de multiplicar el Ancho por 4 pues como solo estoy haciendo un promedio ponderado de los canales no necesito un byte para guardarlos todos (RGB+alpha).

Probé cambiar la asignacion por:

matriz[j] = i+j

para ver que no fuera el tamaño de la matriz lo que prococaba la violacion de segmento y todo fué bien...

Estoy aisla el problema a la parte derecha de la asignación:

(unsigned char)(alpha*R + beta*G + gamma*B );

Pero no veo el problema... =(

Eternal Idol

  • Moderador
  • ******
  • Mensajes: 4696
  • Nacionalidad: ar
    • Ver Perfil
Re: Segmentation Fault...cual Es El Error?
« Respuesta #3 en: Miércoles 28 de Mayo de 2008, 21:42 »
0
Dudo mucho que el problema este ahi, depura el programa. Solo vos tenes el codigo nosotros lo unico que podriamos hacer es tratar de adivinar donde esta el error (yo no tengo ganas de hacerlo).

Nacional y Popular En mi país la bandera de Eva es inmortal.


Queremos una Argentina socialmente justa, económicamente libre y  políticamente soberana.
¡Perón cumple, Evita dignifica!


La mano invisible del mercado me robo la billetera.

JoseTlaseca

  • Nuevo Miembro
  • *
  • Mensajes: 9
    • Ver Perfil
Re: Segmentation Fault...cual Es El Error?
« Respuesta #4 en: Miércoles 28 de Mayo de 2008, 22:55 »
0
Eternal Idol gracias por responder.

¿A que te refieres con depurar? ¿A usar un debugger?

Si es así... no se cual usar, nunca he usado uno... uso kdevelop... me puedes orientar?

Muchas gracias.

Eternal Idol

  • Moderador
  • ******
  • Mensajes: 4696
  • Nacionalidad: ar
    • Ver Perfil

Nacional y Popular En mi país la bandera de Eva es inmortal.


Queremos una Argentina socialmente justa, económicamente libre y  políticamente soberana.
¡Perón cumple, Evita dignifica!


La mano invisible del mercado me robo la billetera.

JoseTlaseca

  • Nuevo Miembro
  • *
  • Mensajes: 9
    • Ver Perfil
Re: Segmentation Fault...cual Es El Error?
« Respuesta #6 en: Miércoles 28 de Mayo de 2008, 23:01 »
0
Gracias nuevamente...
voy a ver los links que me has dejado... espero resolverlo...
Gracias.

JoseTlaseca

  • Nuevo Miembro
  • *
  • Mensajes: 9
    • Ver Perfil
Re: Segmentation Fault...cual Es El Error?
« Respuesta #7 en: Viernes 30 de Mayo de 2008, 06:25 »
0
Creo que ya encontré el verdadero problema... a reserva de que alguien me diga lo contrario:

Tengo un hilo (qthread), en el se generan nombres de archivo que posteriormente se abren con una QImage y se muestran en una ventana, la idea es generar nombres de archivo como sigue:
Imagen0001.bmp
Imagen0002.bmp
...
ImagenXXXX.bmp
(todos estos archivos existen en algun lugar en mi disco duro)

y mostrarlos todos cada vez que se genera su nombre, para dar la apariencia de que es un video, lo ideal es usar una camara que me de las imagenes, pero a falta de ella uso secuencias de archivos.

Bueno, el proceso en general es el siguiente:


hilo::run()
{
   while(contador <= fin)//ESTE WHILE SI TIENE FIN, NO SE VUELVE INFINITO
   {

        //CODIGO PARA GENERAR UN NOMBRE DE ARCHIVO, INCLUYE LA RUTA COMPLETA DEL ARCHIVO
   nombreArchivo = ...
        //TERMINA CODIGO DE GENERAR NOMBRE DE ARCHIVO


   //CREO UN OBJETO QIMAGE CON LA RUTA Y NOMBRE OBTENIDOS ARRIBA
        imageImagen = new QImage(nombreArchivo);

   //CREO UN APUNTADOR PARA MANIPULAR LOS PIXELES DE LA IMAGEN
   pixelImagen = imageImagen->bits();


   //SE PINTA LA IMAGEN EN PANTALLA
   codigo de pintado...
   //TERMINA CODIGO DE PINTADO

        contador++;
   }
}

y creo que el problema está en que me estoy volando la memoria del sistema pues creo en cada iteracion del while una QImage nueva... entonces el cuando el S.O. se da cuenta de eso me para el programa por seguridad (supongo yo).

La solucion sería que fuera del hilo y del while creara la QImage y dentro del while solo decirle que cargue tal imagen, despues "resetear" la imagen, dejarla vacia pues y a la siguiente iteracion cargar la siguiente.

El problema es que no se como hacer eso... pensé que con Load() y Reset() de la clase QImage lo lograría, pero no puedo o no sé como hacerlo...

¿Alguien (Eternal Idol) me puede decir como es la manera correcta de hacer lo que quiero?

Gracias de antemano.

Eternal Idol

  • Moderador
  • ******
  • Mensajes: 4696
  • Nacionalidad: ar
    • Ver Perfil
Re: Segmentation Fault...cual Es El Error?
« Respuesta #8 en: Viernes 30 de Mayo de 2008, 11:41 »
0
Si es eso entonces simplemente deshabilita ese codigo y comproba que todo funcione correctamente. La solucion dependera de lo que quieras hacer exactamente pero tiene pinta de que podes liberarlo justo antes de cambiar por la otra imagen sin necesidad de tener todas en memoria al mismo tiempo ...

Nacional y Popular En mi país la bandera de Eva es inmortal.


Queremos una Argentina socialmente justa, económicamente libre y  políticamente soberana.
¡Perón cumple, Evita dignifica!


La mano invisible del mercado me robo la billetera.

JoseTlaseca

  • Nuevo Miembro
  • *
  • Mensajes: 9
    • Ver Perfil
Re: Segmentation Fault...cual Es El Error?
« Respuesta #9 en: Viernes 30 de Mayo de 2008, 18:32 »
0
Con la novedad de que estaba equivocado... probé usando el codigo sin alterar nada solo no invoqué a la funcion que originalmente pensé que me daba problemas (llenarMatrizOriginal) pero esta vez repitiendo la misma secuencia de imagenes en un ciclo infinito... es decir lo unico que hago es mostrar una secuencia de imagnes una y otra vez con el fin de ver si el hecho de hacer "new QImage (nombreArchivo)" en cada iteracion se estuviera consumiendo la memoria del sistema, pero para mi sorpresa la memoria permanece a un mismo nivel, estuvo en ejecucion unos 10 minutos hasta que detuve el programa, para ver el comportamiento de la memoria usé el screenlet "sysmonitor".

Después decidí debuggear el programa a ver que pasaba y estos fueron los resultados (nótese que reinicie el programa tras la violacion de segmento 3 veces seguidas a fin de mostrar que no siempre marca el error  en el mismo instante, a veces muestra muchas imagenes, a veces solo pocas, pero el error siempre es en la funcion de llenado de la matriz):

pepe@supersonic:~/Tesis/trackeador/bin$ gdb trackeador
GNU gdb 6.8-debian
Copyright © 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...

(gdb) run

Starting program: /home/pepe/Tesis/trackeador/bin/trackeador
[Thread debugging using libthread_db enabled]
Qt: gdb: -nograb added to command-line options.
         Use the -dograb option to enforce grabbing.
[New Thread 0xb71a1ae0 (LWP 25276)]
[New Thread 0xb6ecab90 (LWP 25280)]
Archivo de imagen a abrir: /home/pepe/Tesis/Secuencias/Sec1/Imagen1901.bmp
Archivo de imagen a abrir: /home/pepe/Tesis/Secuencias/Sec1/Imagen1902.bmp
Archivo de imagen a abrir: /home/pepe/Tesis/Secuencias/Sec1/Imagen1903.bmp
Archivo de imagen a abrir: /home/pepe/Tesis/Secuencias/Sec1/Imagen1904.bmp
Archivo de imagen a abrir: /home/pepe/Tesis/Secuencias/Sec1/Imagen1905.bmp
Archivo de imagen a abrir: /home/pepe/Tesis/Secuencias/Sec1/Imagen1906.bmp
Archivo de imagen a abrir: /home/pepe/Tesis/Secuencias/Sec1/Imagen1907.bmp
Archivo de imagen a abrir: /home/pepe/Tesis/Secuencias/Sec1/Imagen1908.bmp
Archivo de imagen a abrir: /home/pepe/Tesis/Secuencias/Sec1/Imagen1909.bmp

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb6ecab90 (LWP 25280)]
0x0804f3a6 in seguimiento::llenarMatrizOriginal ()
Current language:  auto; currently asm


(gdb) r

The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/pepe/Tesis/trackeador/bin/trackeador
[Thread debugging using libthread_db enabled]
Qt: gdb: -nograb added to command-line options.
    Use the -dograb option to enforce grabbing.
[New Thread 0xb7154ae0 (LWP 25282)]
[New Thread 0xb6dcdb90 (LWP 25283)]
Archivo de imagen a abrir: /home/pepe/Tesis/Secuencias/Sec1/Imagen1901.bmp
Archivo de imagen a abrir: /home/pepe/Tesis/Secuencias/Sec1/Imagen1902.bmp
Archivo de imagen a abrir: /home/pepe/Tesis/Secuencias/Sec1/Imagen1903.bmp
Archivo de imagen a abrir: /home/pepe/Tesis/Secuencias/Sec1/Imagen1904.bmp
Archivo de imagen a abrir: /home/pepe/Tesis/Secuencias/Sec1/Imagen1905.bmp
Archivo de imagen a abrir: /home/pepe/Tesis/Secuencias/Sec1/Imagen1906.bmp

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb6dcdb90 (LWP 25283)]
0x0804f3a6 in seguimiento::llenarMatrizOriginal ()


(gdb) r

The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/pepe/Tesis/trackeador/bin/trackeador
[Thread debugging using libthread_db enabled]
Qt: gdb: -nograb added to command-line options.
    Use the -dograb option to enforce grabbing.
[New Thread 0xb71b8ae0 (LWP 25284)]
[New Thread 0xb6e31b90 (LWP 25285)]
Archivo de imagen a abrir: /home/pepe/Tesis/Secuencias/Sec1/Imagen1901.bmp
Archivo de imagen a abrir: /home/pepe/Tesis/Secuencias/Sec1/Imagen1902.bmp
Archivo de imagen a abrir: /home/pepe/Tesis/Secuencias/Sec1/Imagen1903.bmp
Archivo de imagen a abrir: /home/pepe/Tesis/Secuencias/Sec1/Imagen1904.bmp
Archivo de imagen a abrir: /home/pepe/Tesis/Secuencias/Sec1/Imagen1905.bmp

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb6e31b90 (LWP 25285)]
0x0804f3a6 in seguimiento::llenarMatrizOriginal ()


(gdb) q
The program is running.  Exit anyway? (y or n) y



Después use el debugger con el programa sin usar la funcion "llenarMatrizOriginal" y todo fué normal mucho tiempo (no pongo la salida del debugger porque son demasidas lineas "archivo de imagen a abrir...") hasta que yo lo detuve... esto confirma mis sospechas... el problema esta en la susodicha funcion pero no se a que se deba...

JoseTlaseca

  • Nuevo Miembro
  • *
  • Mensajes: 9
    • Ver Perfil
Re: Segmentation Fault...cual Es El Error?
« Respuesta #10 en: Sábado 31 de Mayo de 2008, 07:23 »
0
Una vez mas me desdigo... ¬¬ que verguenza...
El problema si es que me estoy volando la memoria del sistema cada vez que se crea una QImage con la nueva imagen de la secuencia... trataré de buscar la opcion para solo recargar la imagen con una nueva sin crear un objeto nuevo... pero si alguien pudiera ayudarme con eso se lo agradeceré infinitamente...

Eternal Idol

  • Moderador
  • ******
  • Mensajes: 4696
  • Nacionalidad: ar
    • Ver Perfil
Re: Segmentation Fault...cual Es El Error?
« Respuesta #11 en: Domingo 1 de Junio de 2008, 09:26 »
0
Primero asegurate al 100% que sea eso, si es necesario comenta el codigo que crees que es el problema y proba el resto del programa.

Si realmente es esa parte la clave esta, como te dije antes, en crear el objeto justo antes de mostrarlo en pantalla y destruirlo cuando vas a poner otro en la misma.

Nacional y Popular En mi país la bandera de Eva es inmortal.


Queremos una Argentina socialmente justa, económicamente libre y  políticamente soberana.
¡Perón cumple, Evita dignifica!


La mano invisible del mercado me robo la billetera.

JoseTlaseca

  • Nuevo Miembro
  • *
  • Mensajes: 9
    • Ver Perfil
Re: Segmentation Fault...cual Es El Error?
« Respuesta #12 en: Martes 3 de Junio de 2008, 20:01 »
0
(SOLUCIONADO)

En mi codigo uso un evento de usuario para notificarle al hilo principal de la ejecucion que mi hilo QThread ha hecho cambios en la interfaz y que es necesario actualizar... dicho evento tenia el siguiente cuerpo:

/*************************************************************************
*******************************CUSTOM EVENT*******************************
Evento que hace un repintado de la imagen y elimina el apuntador utilizado
ya que en el run del hilo se crea uno por imagen a mostrar
*************************************************************************/
void igu_trackeador::customEvent (QCustomEvent * e)
{
    if ( e->type() == QEvent::User )
    {
        painter->dibujarImagen(imageImagen);
        delete imageImagen;
        repaint(FALSE);
        actualizar = TRUE;
    }
}

Si notan en este evento elimino el apuntador imageImagen, entonces si usaba funciones miembro de la clase QImage como load() o reset() me marcaba un error y el programa se salia...
Ademas en mi hilo principal creaba una QImage nueva en cada iteracion (lo tenia que hacer asi porque el evento eliminaba la anterior)...

La solucion es es la siguiente:

en el archivo .h de mi clase declaré una sola vez el apuntador imageImagen de tipo QImage como sigue:

//crea una QImage limpia de 32 bits de profundidad
//ancho imageAncho y alto imageAlto
imageImagen = new QImage(imageAncho, imageAlto, 32);


y en el hilo sustituí la linea imageImagen = new QImage(nombreArchivo);

por la siguiente:

imageImagen->load(nombreArchivo);

Ya que esta ultima linea no me esta creando una nueva QImage, sino que solo carga la siguiente (depende del contenido de nombreArchivo) de la secuencia... que es lo que quiero =)

y por ultimo en el cuerpo del evento de repintado eliminé la linea "delete imageImagen;" pues ya no estoy creando una imagen en cada iteracion y si la elimino me marcaria error...

Notese que usando load() ya no tengo que usar reset() en ninguna parte...


En resumen:

1.- declarar un apuntador (en mi caso necesito que sea apuntador) de tipo QImage en el erchivo .h

2.- en el constructor de la clase crear una QImage vacia...

3.- en el hilo que carga la secuencia de imagenes solo utilizar la funcion load() para actualizar el contenido de la variable de imagen...

4.- refrescar la pantalla (yo uso un postEvent)

5.- no es necesario eliminar el apuntador QImage en cada iteracion... SOLO se debe eliminar cuando ya no se vaya a usar mas o hasta que la aplicacion termine.

Ahora mismo ya estoy realizando seguimiento de objetos en una secuencia... he probado la solucion que aqui menciono repitiendo infinitamente la misma secuencia y todo ha ido bien... ahora mismo van 31 minutos y el programa y la memoria estables...



Muchas gracias EternalIdol por tenerme paciencia... sin tu ayuda habria sido mas dificil...

Espero que mi experiencia le sirva a alguien...

Jose Tlaseca.