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],csWarum 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
-
Memory-Breakpoints sollten auch noch erwähnt sein: