virtual member -> vtable problem
-
Hallo allerseits,
ich habe ein kleines Problem mit virtuellen Memberfunktionen, indem mir das Programm gnadenlos abstürzt.
Ziel: Die Basisklasse soll per default OnCreate, On Destroy, etc implementieren. Die abgeleitete Klasse kann diese per Bedarf überschreiben. In der WndProc werden, falls nix anderes definiert, die Basismethoden aufgerufen. Bei eigener Impelementation sollen die der abgeleiteten Klasse genommen werden. So habe ich mir gedacht, das das mit den virtuellen Membern so klappt. Leider stürzen Kompilate mit MinGW || VC08 ab. Der VC sagt mir wenigstens noch, das scheinbar ein Problem mit der vtable vorliegt. Was mache ich falsch? Wenn ich das virtual entferne, läuft es wenigstens, aber es werden nicht die der Abgeleiteten Klasse benutzt.
Windows Basisklasse
#ifndef WINDOW_H_INCLUDED #define WINDOW_H_INCLUDED #include "wfw.h" class Window { private: static LRESULT WINAPI StaticWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); LRESULT WINAPI WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); protected: public: Window(); Window(std::string title, unsigned int width, unsigned int height); virtual ~Window(); ///public WndProc functions virtual BOOL OnCreate(HWND hwnd, WPARAM wParam, LPARAM lParam); //virtual macht Probleme virtual BOOL OnDestroy(HWND hwnd, WPARAM wParam, LPARAM lParam); //virtual macht Probleme ///public functions BOOL Create(std::string title = "untitled", unsigned int width = 640, unsigned int height = 480); }; #endif // WINDOW_H_INCLUDEDAusschnitt aus der Windows Basisklasse
LRESULT WINAPI Window::StaticWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { if(msg == WM_CREATE) { SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)lParam); } Window *wnd = (Window*)GetWindowLongPtr(hwnd, GWLP_USERDATA); if(!wnd) { return DefWindowProc(hwnd, msg, wParam, lParam); } else { return wnd->WndProc(hwnd, msg, wParam, lParam); } } LRESULT WINAPI Window::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_CREATE: return OnCreate(hwnd, wParam, lParam); //hier stürzt er ab break; case WM_DESTROY: return OnDestroy(hwnd, wParam, lParam); //hier stürzt er ab break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return DefWindowProc(hwnd, msg, wParam, lParam); }Das abgeleitete Fenster mit den eigenen Deklarationen
class MyWindow: public Window { public: MyWindow() { } MyWindow(std::string title, unsigned int width, unsigned int height) { std::cout << Create(title, width, height) << std::endl; } virtual ~MyWindow() { } BOOL OnCreate(HWND hwnd, WPARAM wParam, LPARAM lParam) { //std::cout << "derived class" << std::endl; //MessageBox(hwnd, "Just created", "Message", MB_ICONINFORMATION | MB_OK); return FALSE; } BOOL OnDestroy(HWND hwnd, WPARAM wParam, LPARAM lParam) { //PostQuitMessage(0); return FALSE; } private: };Aufruf
MyWindow wnd("Window", 800, 600);
-
Du solltest auch schon den Destruktor der Basisklasse virtuell machen:
virtual ~Window();
-
Bin ich gerad schief gewickelt, oder muss nicht der Destruktor auch virtual?
Edit: oh, zu spät. naja

-
VirtualDreams schrieb:
Hallo allerseits,
...
Zitat: "Ich habe ein Programm geschrieben und das funst nich. Warum nich
Jetzt warte ich schon über 10 Minuten und es hat immer noch keiner geantwortet.
Könnt ihr das nich ?"Verarscht du dich mit deiner Signatur selbst?
-
Isst inzwischen nachgezogen. Ändert aber erst mal nichts an dem Fehler.

-
sagmal schrieb:
VirtualDreams schrieb:
Hallo allerseits,
...
Zitat: "Ich habe ein Programm geschrieben und das funst nich. Warum nich
Jetzt warte ich schon über 10 Minuten und es hat immer noch keiner geantwortet.
Könnt ihr das nich ?"Verarscht du dich mit deiner Signatur selbst?
Nein, ist schon lange her aus dem Delphiforum von einem neuen User ^^
-
nimm mal nen debugger und schau wo es crasht
-
case WM_CREATE: return OnCreate(hwnd, wParam, lParam); //hier stürzt er ab break; case WM_DESTROY: return OnDestroy(hwnd, wParam, lParam); //hier stürzt er ab break;Er schafft es nicht die beiden Funktionen aufzurufen:
- this 0x0029efb8 Window * const - __vfptr 0x0029f7b0 * [0x0] 0x00ce780c const Window::`vftable' * [0x1] 0xcccccccc * //fehler [0x2] 0x0029f864 *
-
VirtualDreams schrieb:
virtual ~MyWindow() // ...Das ist m.E. überflüssig, weil der Destruktor jetzt in der Basisklase virtual ist und es damit auch in der abgeleiteten Klasse sein sollte.
Der Grund für den Fehler sollte das aber eigentlich nicht sein. Hm.
-
if(msg == WM_CREATE) { SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)lParam); } Window *wnd = (Window*)GetWindowLongPtr(hwnd, GWLP_USERDATA);Sicher, dass das so richtig abläuft?
-
David_pb schrieb:
if(msg == WM_CREATE) { SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)lParam); } Window *wnd = (Window*)GetWindowLongPtr(hwnd, GWLP_USERDATA);Sicher, dass das so richtig abläuft?
Ja, wenn virtual entfernt ist funktioniert das einwandfrei.
-
VirtualDreams schrieb:
Ja, wenn virtual entfernt ist funktioniert das einwandfrei.
Was nicht heißt das dein Code korrekt ist...
-
Reduzier dein Problem auf das Wesentliche. Überprüfe, ob der Fehler immer noch auftritt, wenn du die Windows-Anweisungen weglässt, bis du nur noch leere Klassen hast. So kannst du relativ schnell feststellen, welcher Codeteil für den Fehler verantwortlich ist.
-
Witziger Fehler, hab es gefunden
Statt
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)lParam);muss es so gemacht werden
Window *w = (Window*)((LPCREATESTRUCT)lParam)->lpCreateParams; SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)w);da lParam nur ein weiterer Pointer auf die Struct ist. Hab es nur dadurch gefunden weil lParam den pointer auf die vtable enthalten hatte...
Trotzdem vielen Danke für eure Mühe!

-
VirtualDreams schrieb:
Witziger Fehler, hab es gefunden
Statt
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)lParam);muss es so gemacht werden
Window *w = (Window*)((LPCREATESTRUCT)lParam)->lpCreateParams; SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)w);da lParam nur ein weiterer Pointer auf die Struct ist. Hab es nur dadurch gefunden weil lParam den pointer auf die vtable enthalten hatte...
Neiiiin, ehrlich?

-
Was hat das alles mit Standard-C++ zu tun?
-
Jetzt nichts mehr, ich dachte erst, es würde was mit virtuellen Membern zu tun haben.
[quote="David_pb"]
VirtualDreams schrieb:
Witziger Fehler, hab es gefunden
...
Neiiiin, ehrlich?

Bitte weniger Sarkastisch, ich hatte es einfach vergessen, das da noch ne struct dahinter hängt. Keiner ist perfekt...
-
[quote="VirtualDreams"]Jetzt nichts mehr, ich dachte erst, es würde was mit virtuellen Membern zu tun haben.
David_pb schrieb:
VirtualDreams schrieb:
Witziger Fehler, hab es gefunden
...
Neiiiin, ehrlich?

Bitte weniger Sarkastisch, ich hatte es einfach vergessen, das da noch ne struct dahinter hängt. Keiner ist perfekt...
Ich hab dir doch sogar nen Tipp gegeben...
-
OK, dann hab ich falsch interpretiert. Bin ja noch den Dingen nachgegangen, aber muss einfach nur übersehen haben ^^