Debuggen mit VC++6



  • Ich dachte es mir auch schon, ich habe zwar keine guten Erinnerungen an den VC++ 6, aber dass er derartig ... ungewöhnlich ... war, daran konnte ich mich auch nicht mehr erinnern. 😉
    Alles in allem ein sehr praxisnaher Artikel, der vor allem die Grundlagen IMHO sehr großflächig abdeckt. In einem Foren-Archiv macht er sich sicher gut, bei einem Print-Magazin hätte ich persönlich höhere Ansprüche bzgl. der Kenntnis des Lesers vorausgesetzt. Aber in der Form sicherlich ideal.



  • Hallo,

    mal ne (dumme?) Frage:

    Ich finde diesen Beitrag sehr toll, da ich bisher wirklich nix mit dem Debugger anfangen konnte. Aber ASEERT Und VERIFY werden leider nicht erkannt
    (Ich benutze MS Viasual c++ standard)

    Muss ich da noch was inkludieren? Und werden diese ASSERT bei der Release Version automatisch entfernt oder muß ich nor irgendwo was einstellen?



  • ich glaube ein #include <assert.h> hilft hier 🙂



  • Das ist kein Lila, das ist Blau. :p Bei Autos finden das alle sooooo cool. 🤡

    @Anfänger: Du musst nichts mehr einstellen, das ist automatisch so. 🙂



  • estartu_de schrieb:

    Das ist kein Lila, das ist Blau. :p Bei Autos finden das alle sooooo cool. 🤡

    na hoffentlich hat das kennzeichen deines VW busses nicht SO eine schriftart, sonst müssten die armen polizisten ja augenkrebs kriegen... 🙂

    Mr. B



  • Tach, ich habe auch noch eine Frage zum Debuggen.

    ich habe folgendes Programm mit dem Debugger gestartet:

    #include <windows.h>
    
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain(
    				   HINSTANCE hInstance,				//Identifikationswert
    				   HINSTANCE hPrevInstance,			//Veraltet und unnötig es nochmals aufzurufen
    				   PSTR szCMDLine,					//Kommandozeilenpararmeter
    				   int iCmdShow						//Kontrolliert das Aussehen des fensters
    				   )
    {
    
    	static TCHAR szAppName[] = TEXT("Hello");
    
    	HWND hwnd;										//Handle für ein Fenster							
    	MSG msg;										//Nachrichten
    	WNDCLASS wndclass;								//Fensterklasse
    
    	wndclass.style               = CS_HREDRAW | CS_VREDRAW; //Klassenstile
    	wndclass.lpfnWndProc         = WndProc;				 //Funktion für Nachrichtenauswertung
    	wndclass.cbClsExtra          = 0;			//Zusatzspeicher im Rahmen von Fensterklassen
    	wndclass.cbWndExtra          = 0;			//Zusatzspeicher in Fenstern	
    	wndclass.hInstance           = hInstance;	//eigene Instanz Kennziffer won WinMain
    	wndclass.hIcon               = LoadIcon(NULL, IDI_APPLICATION);	//Lädt das Icon
    	wndclass.hCursor             = LoadCursor (NULL, IDC_ARROW);		//Lädt den Curser
    	wndclass.hbrBackground       = (HBRUSH) GetStockObject (WHITE_BRUSH);//Hintergrundfarbe setzen
    	wndclass.lpszMenuName        = NULL;		//Festlegen des Menüs
    	wndclass.lpszClassName       = szAppName;	//Namen der Fensterklasse
    
    	if (!RegisterClass(&wndclass))						//definiert die angegebene Fensterklasse
    	{	
    		MessageBox (
    			NULL,
    			TEXT ("Programm arbeitet mit Unicode und braucht Windows: 2000, NT, XP, oder neuer!"),
    			szAppName,
    			MB_ICONERROR
    		);
    
        return 0;
    	}
    
    	hwnd = CreateWindow (					//erzeugt ein Fenster auf Basis einer Fensterklasse
    						szAppName,					//Name der FensterKlasse
    						TEXT ("Nur ein Fenster"),	//Fenstertitel
    						WS_OVERLAPPEDWINDOW,		//Fensterstil
    						CW_USEDEFAULT,				//X-Position des Fensters
    						CW_USEDEFAULT,				//Y-Position des Fensters
    						CW_USEDEFAULT,				//Fensterbreite
    						CW_USEDEFAULT,				//Fensterhöhe
    						NULL,						//Übergeordnetes Fenster
    						NULL,						//Menü
    						hInstance,					//Programm-Kopiezähler (Programm-ID)
    						NULL						//zusätzliche Prarmeter
    						);
    
    	ShowWindow (hwnd, iCmdShow);					//stellt das Fenster auf dem Bildschirm da					
    	UpdateWindow(hwnd);								//Fenster soll seinen Inhallt darstellen
    
    	while (GetMessage (&msg, NULL, 0, 0))			//Holt Nachricht aus der Warteschlange
    	{
    		TranslateMessage(&msg);						//setzt Tastaturnachrichten um
    		DispatchMessage(&msg);						//senden der Windows_Prozedur Nachrichten
    	}
    	return msg.wParam;							
    
    }
    
    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	HDC	hdc;
    	PAINTSTRUCT ps;
    	RECT rect;
    
    	switch (message)
    	{
    	case WM_CREATE:
    
    		return 0;
    
    	case WM_PAINT:
    
    		hdc = BeginPaint (hwnd, &ps);	//Teilt Windows mit, das mit Zeichnen begonnen wird
    
    		GetClientRect (hwnd, &rect);	//Ermitteld die Größed es Anwendungsbereichs des Fensters
    
    		DrawText(hdc, TEXT("Hallo"),-1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    		EndPaint (hwnd, &ps);			//Teilt Windows mit, das mit Zeichnen beendet wird
    		return 0;
    
    	case WM_DESTROY:
    
    		PostQuitMessage (0);			//setzt Nachricht "Ende" in Nachrichtenwarteschlange
    		return 0;
    	}
    
    	return DefWindowProc (hwnd, message,wParam, lParam);//Bearbeitet nicht abgefangene Nachrichten	
    }
    

    Das Programm ist fehlerfrei (denke ich mal). Wenn ich den Debugger aber anhalte wird mir folgendes angezeigt:

    7C91EB94 ret
    7C91EB95 lea esp,[esp]
    7C91EB9C lea esp,[esp]
    7C91EBA0 nop
    7C91EBA1 nop
    7C91EBA2 nop
    7C91EBA3 nop
    7C91EBA4 nop
    7C91EBA5 lea edx,[esp+8]
    7C91EBA9 int 2Eh
    7C91EBAB ret
    7C91EBAC push ebp
    7C91EBAD mov ebp,esp
    7C91EBAF pushfd
    7C91EBB0 sub esp,2D0h
    7C91EBB6 mov dword ptr [ebp-224h],eax
    7C91EBBC mov dword ptr [ebp-228h],ecx
    7C91EBC2 mov eax,dword ptr [ebp+8]
    7C91EBC5 mov ecx,dword ptr [ebp+4]
    7C91EBC8 mov dword ptr [eax+0Ch],ecx
    7C91EBCB lea eax,[ebp-2D4h]
    7C91EBD1 mov dword ptr [eax+0B8h],ecx
    7C91EBD7 mov dword ptr [eax+0A4h],ebx
    7C91EBDD mov dword ptr [eax+0A8h],edx
    7C91EBE3 mov dword ptr [eax+0A0h],esi
    7C91EBE9 mov dword ptr [eax+9Ch],edi
    7C91EBEF lea ecx,[ebp+0Ch]
    7C91EBF2 mov dword ptr [eax+0C4h],ecx
    7C91EBF8 mov ecx,dword ptr [ebp]
    7C91EBFB mov dword ptr [eax+0B4h],ecx
    7C91EC01 mov ecx,dword ptr [ebp-4]
    7C91EC04 mov dword ptr [eax+0C0h],ecx
    7C91EC0A mov word ptr [eax+0BCh],cs

    Warum wird ncht mein Code gezeigt. Außerdem, wenn ich in einzelschritten fortsetzen nmache, geht das vielleicht ca. 20 mal. Danach weigert sich der Debugger überhaupt was zu tun!

    Bei linearen Konsolenanwendung zeigt er mir aber ganz normal meinen code und auch sonst ist dort alles in ordnung!

    Mache ich etwas falsch?



  • MisterX schrieb:

    Warum wird ncht mein Code gezeigt. Außerdem, wenn ich in einzelschritten fortsetzen nmache, geht das vielleicht ca. 20 mal. Danach weigert sich der Debugger überhaupt was zu tun!

    Bei linearen Konsolenanwendung zeigt er mir aber ganz normal meinen code und auch sonst ist dort alles in ordnung!

    Mache ich etwas falsch?

    Also, ich vermute, du bist irgendwo in der API gelandet. Für die gibt es wohl keinen Quellcode (zumindest wurde er nicht gefunden) und deswegen bekommst du nur Assemblercode.

    Warum er sich aufhängt, weiß ich nicht. 😞
    Läuft es denn normal, wenn du es nicht anhälst?

    Wie sieht dein Callstack aus? Findest du dort deinen Code?



  • MisterX schrieb:

    Außerdem, wenn ich in einzelschritten fortsetzen nmache, geht das vielleicht ca. 20 mal. Danach weigert sich der Debugger überhaupt was zu tun!

    Kanns sein, dass du dich in einer Schleife befindest, die vielleicht ca. 20 mal durchlaufen wird und dann das Programm bis zum Ende ausgeführt wird?



  • Tach,

    ich habe das Programm (Das definitiv OK ist) jetzt auch mal mit dem Debugger getestet.

    Es passiert folgendes:
    Das Programm erzeugt das Fenster. Nun drückst du die Taste zum Stoppen des Debuggers. Das Fenster wird also in den Hintergrund gestellt und erhält (weil der Debugger im Vordergrund ist) keine WM_PAINT Befehle.
    Also befindet man sich nur noch in der Nachrichten schleife, die ohne was zu tum abgearbeitet wird. Danach kommen keine weiteren Nachrichten. Komischerweise verträgt der Debugger das nicht und stürtzt ab - hab ich mit dem Visual c++ 6.0 Compiler (Mit den neuesten Updates getestet).
    Das Programm ist definitiv noch nicht beendet, da das Fenster wieder in den Vordergrund geholt werden kann. Der Debugger reagiert aber nicht mehr!

    Wenn du allerdings das Fenster wieder in den Vordergrund holst und somit ein Neuzeichnen erzeugst BEVOR du die Einzelschritte ausführst stürzt er NICHT bei ca 20 Weiteren Einzelschritten ab.

    Deine (komische Ausgabe) ist Assemblercode. Das kommt bei mir auch. Du befindest dich dann in irgendeiner Dll. Wahrscheinlich eine die irgendwie für die Nachrichtenauswertung zuständig ist.
    Und genau dort stürtzt der Debugger auch bei mir ab!

    77D4F628   nop
    77D4F629   nop
    77D4F62A   mov         edi,edi
    77D4F62C   push        ebp
    77D4F62D   mov         ebp,esp
    77D4F62F   sub         esp,0Ch
    77D4F632   mov         eax,dword ptr [ebp+8]
    77D4F635   push        dword ptr [eax+10h]
    77D4F638   and         dword ptr [ebp-8],0
    77D4F63C   and         dword ptr [ebp-4],0
    77D4F640   lea         ecx,[eax+8]
    77D4F643   push        ecx
    77D4F644   push        dword ptr [eax+4]
    77D4F647   push        dword ptr [eax]
    77D4F649   call        dword ptr [eax+14h]
    77D4F64C   push        0
    77D4F64E   push        0Ch
    77D4F650   pop         edx
    77D4F651   lea         ecx,[ebp-0Ch]
    77D4F654   mov         dword ptr [ebp-0Ch],eax
    77D4F657   call        77D194A4                 //genau hier ist der Absturz
    77D4F65C   leave
    77D4F65D   ret         4
    77D4F660   nop
    77D4F661   nop
    77D4F662   nop
    77D4F663   nop
    77D4F664   nop
    77D4F665   mov         edi,edi
    77D4F667   push        ebp
    77D4F668   mov         ebp,esp
    77D4F66A   push        1
    77D4F66C   push        dword ptr [ebp+18h]
    77D4F66F   push        dword ptr [ebp+14h]
    77D4F672   push        dword ptr [ebp+10h]
    77D4F675   push        dword ptr [ebp+0Ch]
    77D4F678   push        dword ptr [ebp+8]
    77D4F67B   call        77D3082F
    77D4F680   pop         ebp
    77D4F681   ret         14h
    

    PS. Ich kenne mich mit Assembler nicht so aus.
    Was macht genau diese Anweisung bei der es schief geht?



  • Nun drückst du die Taste zum Stoppen des Debuggers.

    Warum das denn??? Kein Wunder das du in den Tiefen des Betriebssystems landest. Das ist ja schon wie Roulettspielen. 🙄

    Mach mal nen Breakpoint in deinen Sourcecode rein (z.B. in einen Ereignis-Einsprung). Und wenn du das Ereignis ausführst (z.B. durch drücken eines Buttons), wird dein Programm an der Stelle des Breakpoints unterbrochen.



  • Das ist auch nur für den Fall gedacht, dass man mit den schon erwähnten Hilfsmitteln nicht mehr weiter kommt.
    Wenn ich gar keine Ahnung habe, wo das Problem liegt, dann drücke ich Pause und gucke dann im Callstack. So habe ich noch alles gefunden. 🙂

    Manchmal sind die Fehler nämlich nicht da, wo man denkt.



  • wie wärs mit einer PDF Version des Artikels? ist so etwas umständlich zum ausdrucken




Anmelden zum Antworten