Tengo una clase que deriva de otra, que a su vez deriba de otra:
Texture -> Reource -> Object
El problema surge cuando instancío texture y llamo a un método virtual de texture (que no tienen sus padres) llamado Create, entonces el visual me avisa de que algo raro está pasando porque la pila no encaja bien, entonces debugo y veo que efectivamente al llamar a mi método virtual se me está ejecutando un método totalmente distinto, no el mismo método en la clase padre, directamente uno con parametros y retorno diferente, que obviamente me está dejando la pila hecha un cristo y el visual se da cuenta al ver que no encaja el numero de bytes allocados.
Bien, hasta aquí yo podría pensar - en algun momento he jodido la tabla de funciones virtuales al salirme de algun array o hacer un memset - pero realmente no hay nada raro, creo la instancia, y lo siguiente que hago es llamar al metodo virtual, y los constructores son muy simples, solo ponen a cero las variables (no uso nunca memcpys o memsets, directamente igualo a cero).
Desesperado se me ocurre heredar de Texture una clase Foo, instanciarla y llamar a mi metodo virtual Create, y entonces sí funciona. O sea que Foo sí que deja bien la tabla de funciones virtuales, Texture no.
Intento debugar la tabla para ver si en algun momento se cambia pero en mi tabla de funciones virtuales no sale mi método Create, salen solo los de la clase padre, supongo que el compilador si ve que un metodo no tiene dos implementaciones entonces se ahorra reservarle espacio en la tabla de funciones.
En fin, es desesperante y llevo ya un día perdido con esta chorrada, debería intentar aislar el problema pero es una clase enorme que usa todo mi framework y está jodido.
Si alguien tiene alguna idea se lo agradeceré (aunque como alguien me venga con - has puesto la palabra virtual delante del nombre de la funcion? - me pondré muy tenso... y no quereis que me ponga tenso)
¿Qué ocurre si eliminas la cabecera de la función virtual Create? ¿Se queja el compilador? (Dicho de otra forma: ¿encuentra la función aunque no la hubieras declarado?)
Segunda idea: ¿Qué ocurre si añades a los padres la función virtual Create vacía? ¿Sigue funcionando mal?
Estas usando punteros o referencias de las instancias, o estas usando las instancias directamente? Pon el codigo relevante del problema, anda :)
Respondiendo a Mars:
Si quito la funcion peta el compilador, no tiene pinta de usar otra funcion, de hecho probé de cambiarle el nombre no sea que por Create pillase algo de windows, pero hacía lo mismo
Lo de ponerle la funcion a los padres lo pensé pero por desgracia algunos parametros son enums de la clase Texture así que está dificil, pero lo intentaré cambiando algunas cosas.
Respondiendo a AK:
Uso punteros, podría poner el codigo pero no vereis nada raro, es todo muuuy estandar, por ejemplo:
class Texture : public Resource
{
//...
virtual const char* tellmefoo() { return "foooo!"; }
virtual const char* ozu(int a,int b,int c) { return "foooo2!"; }
};
//...
Texture* texture = new Texture();
texture->ozu(1,2,3);
Al debugar la llamada a ozu veo que entra en tellmefoo.
En fin, entiendo que es un error rarisimo en el que pueden afectar mil cosas, es solo que ha aparecido de la nada y me tiene algo desesperado, tendré que reducirlo a lo minimo... pero joder, para unas navidades que tenía tiempo para programar y me las paso en esta mierda...
Gracias por las respuestas
Puestos a aislar he creado esta mini aplicacion donde sucede el error, así que paso a remirar linea a linea los constructores (por eneaba vez)
#include <iostream>
#include "HH.hxx"
void main()
{
HH::Texture* t = new HH::Texture;
t->ozu(1,2,3); //<-- Llama a tellmefoo();
}
Perdona si no he entendido bien el código pero, para que usas virtual en la hija ?
virtual es para definir una función que va a ser polimórfica, así la clase será tratada como abstracta y no referenciable y se ponen en los padres, si la defines en el hijo no tiene uso o significado.
tal vez porque alguien hereda de Texture y reimplementa ese método... como RenderTexture. En serio, no busco consejos sobre POO, llevo muchos años en el gremio
En lo que pones no veo nada raro, pero por decir algo que suele ser usual: Las funciones virtuales no se pueden llamar desde los constructores. Lo mismo no es eso, pero para ir descartando cosas.
sip, eso está descartado, de hecho ningun constructor llama a ninguna función.
Pero no le deis vueltas, suena a error muchungo, regiones de memoria que se solapan, algo así, cuando lo descubra ya os lo diré, pero era por saber si alguien había experimentado algo parecido.
Poner una funcion a virtual no hace que la clase sea abstracta y no se pueda instanciar, eso solo pasa con las funciones virtuales puras (esos con virtual tralari = 0)
pero si aquí nadie está hablando de clases virtuales puras, leñe. Que esto no es un thread de - enseñanos cuanto sabes de POO - sino sobre errores chungos con la tabla de punteros a funciones virtuales.
Has una copia del proyecto entero y ve borrando partes que creas no intervengan, cuando deje de hacer la falla te fijas que cambiaste ultimo.
eso he intentado, pero está dificil porque es un proyecto con demasiadas dependencias. Para colmo he hecho un miniproyecto que usa el framework y al ejecutar me pide la opengl.dll cuando nunca me había pedido esa dll (siempre me pedía la opengl32.dll), alguien sabe qué diferencia hay? yo linko contra opengl32.lib así que no entiendo a qué viene opengl.dll
Tienes la posibilidad de probar con otro compilador? Ni que fuera una versión distinta del visual.
Saludos!
Has declarado tus clases en un espacio de nombres? Lo pregunto porque se me ocurre una hipótesis pelín peliaguda, pero dado lo chungo del asunto no estaría de más descartar.
A ver, supongamos que en alguno de los archivos de cabecera que hayas incluido en tu proyecto, digamos alguno de opengl, se define una clase con el mismo nombre que la tuya, Texture, supongamos, y van dos, que alguna de las constructoras de esa clase de ogl admite los mismos argumentos que la constructora de tu clase Texture; supongamos, que pesadito!!!, que esa clase implementa un método que se llama ozu(), esto ya sería la leche de la coincidencia, y por último vamos a suponer que ese método ozu() ejecuta otro método de su misma clase cuando se le llama, supón que es un método privado, y que se llama tellmefoo(), la releche!!!!
Al crear una instancia de Textura el compilador debería cuando menos avisar de que hay dos clases con el mismo nombre y que no sabe a cual te estás refiriendo, salvo que en alguna parte del código haya alguna instrucción del tipo "using namespace espacio_opengl" que le indique al compilador que la clase Texture que ha de instanciar no es la tuya sino la de ogl.
Además esto también podría explicar el problema de las dll.
Bueno, ya avisé que era descabellado, igual me he pasao.
Cita de: tamat en 03 de Enero de 2009, 11:14:00 PM
pero si aquí nadie está hablando de clases virtuales puras, leñe. Que esto no es un thread de - enseñanos cuanto sabes de POO - sino sobre errores chungos con la tabla de punteros a funciones virtuales.
Lo decia por lo que ha comentado Buffon, na mas ;)
HarvesterOfAcorns uso un namespace propio, así que descartado.
AK47, sorry, estoy algo susceptible
¿Cómo llevas el tema tamat? Tengo bastante curiosidad por saber si es o no del compilador...
Tiene toda la pinta, mañana lo probaré en el trabajo a ver, porque he reducido el problema al absurdo y sigue sucediendo. Os mantendré informado.
Yo creo que es porque linko contra una LIB creada por mi y algo pasa (pese a usar el mismo convention en todo y haber funcionado siempre).
De hecho si omito la llamada a la función que me daba problemas todo lo demas funciona perfectamente, lo cual lo hace aun más extraño.
Compilas con una cabecera y linkeas con otra!!!!!!
jaajajaj
No olvidarse tampoco del "Rebuild All" o similares, que algunas veces queda morralla por ahi que hace que todo se vaya al traste >.<
jo tamat nos vas a dejar con la intriga! gcc power!!!