Programozás | C / C++ » Debugging tips and techniques with Visual C++

Alapadatok

Év, oldalszám:2012, 27 oldal

Nyelv:angol

Letöltések száma:45

Feltöltve:2012. november 18.

Méret:251 KB

Intézmény:
-

Megjegyzés:

Csatolmány:-

Letöltés PDF-ben:Kérlek jelentkezz be!



Értékelések

Nincs még értékelés. Legyél Te az első!


Tartalmi kivonat

Debugging Tips & Techniques With Visual C++ Introduction Debugging is the process of weeding out the “undesirables” in our code. Visual C++, along with the tools and libraries that come with it provide a rich set of functionality to aid in the debugging process. This training is by no means an exhaustive list of topics, tips and techniques for debugging. It does cover some common customer issues and ways to handle them. Symbols, PDBs and DBGs When you build a project targeted for “Win32 Debug”, the compiler builds a symbol table to keep track of programming constructs like variable and function names, line numbers, constants, classes, etc. This table is stored in a separate file called a Program Database(PDB). The absolute path to a PDB file is embedded in an .EXE or DLL If the debugger cant find the PDB file at that location or if the path is invalid (for example, if the project was moved to another computer), the debugger looks for it in the current directory. DBG files

are similar to PDB files in that they contain symbolic debugging information. The difference with DBG files are that they are in Portable Executable (PE) file format, and contain sections with COFF(Common Object File Format). COFF is a format for debugging information that is used by other debuggers. The Visual C++ debugger can also use DBG files as long as they contain debugging information in Codeview format. These are useful for debugging when the source code is not available. Even without the source, DBG files allow you to set breakpoints on functions, watch variables, and see the functions in the callstack. They are also required for OLE RPC debugging When working with symbols from a .DBG file, you must use the fully decorated names For example, to set a breakpoint on a call to the Windows sndPlaySound function, you would specify sndPlaySoundA@8 as the location. To generate a .dbg file in this format, you can use REBASEEXE, which comes with Visual C++. For more information, see

Knowledge Base article Q216356 "INFO: Visual C++ Project Settings and .DBG file creation" For more information, see Knowledge Base article Q121366 "INFO: PDB and DBG Files - What They Are and How They Work". Enterprise and Support Training Microsoft Confidential November 2012 2 Hiba! A(z) Heading 1 itt megjelenítendő szövegre történő alkalmazásához használja a Kezdőlap lapot. Setting Breakpoints Breakpoints tell the debugger where or when to break execution of a program. When the program is halted at a breakpoint, you can examine the state of your program, step through your code, and evaluate expressions using the debugger windows. This section contains some tips on setting breakpoints and other issues you may run into. • Setting breakpoints using code. You can force breakpoints in code by calling DebugBreak(), CrtDbgBreak(), the MFC function AfxDebugBreak(), or by generating an int 3 ( asm { int 3 }). • Break at memory address. If you

have a memory address from a GPF dialog or the Disassembly window, and want to break at that address: 1. Open the Breakpoints dialog and click on the Location tab 2. Type in the address preceded by a “0x” This comes in handy when an exception is only reproducible in release mode or when you need to break in a module you don’t have source code for like a system DLL. Enterprise and Support Training • Break on Windows message. To break on any Windows message: 1. Open the BreakPoints dialog and click on the Messages tab. 2. Type in your WndProc function (AfxWndProc for an MFC app). 3. Select the message you want to break on from the drop-down list. Microsoft Confidential November 2012 3 Hiba! A(z) Heading 2 itt megjelenítendő szövegre történő alkalmazásához használja a Kezdőlap lapot. • Conditional break. Let’s say you are having problems with a function whenever one of it’s arguments has a certain value. This function is called all the time with

the argument set to other values so you don’t necessarily want to set a simple breakpoint. You can set a conditional breakpoint in this case: 1. Set a breakpoint in the function (F9). 2. In the Breakpoints dialog, highlight the breakpoint and click on the Condition button. 3. Set a condition like nMsg==6. You can also set conditional breakpoints based on function arguments even without the source or symbols for the function’s arguments. Let’s say you want to set a conditional breakpoint on AfxWndProc whenever the message is WM ACTIVATE(0x06), but you don’t have the source for AfxWndProc and you don’t know what the Message argument is called. You can refer to any of the function’s arguments using the stack pointer (ESP) Instead of typing “nMsg==6” you can type in “*(unsigned int)(@esp+8)==6”. The cast just tells the debugger what the pointer is pointing to. “@esp+8” says start at the stack pointer plus 8 bytes. First 4 bytes points to the return address

(caller) Next 4 bytes points to the HWND argument. The next 4 bytes points to the Message argument Enterprise and Support Training Microsoft Confidential November 2012 4 Hiba! A(z) Heading 1 itt megjelenítendő szövegre történő alkalmazásához használja a Kezdőlap lapot. • Break on the Nth time. If the customer says a function fails around the 50th time it’s called, there’s a way to test this and break right before it happens. The Conditional button under the Location tab in the Breakpoints dialog allows you to set the number of times a function is called before you want to break. If you don’t know how many times the function is called before it fails, set this to well over the suspected number. When the function fails, open the Breakpoints dialog, it will show you how many times the breakpoint has been skipped. 1. Set a breakpoint in the function (F9). 2. In the Breakpoints dialog, highlight the breakpoint and click on the Condition button. 3. Under

“Enter the number of times to skip before stopping” enter a number like 10. • Break on exception. By default, DevStudio will merely print a message in the output window whenever an exception is thrown and handled. If it is not handled, then DevStudio will stop execution. If you want to stop whenever a particular type of exception is thrown, you can select “Stop Always” in the Exceptions dialog under Debug/Exceptions. This can only be done while you’re stopped in the debugger • 1. 2. 3. Enterprise and Support Training Break on change in variable. To break when a variable changes value: Set a breakpoint where the variable is in scope (e.g class constructor) Run the project until you hit the breakpoint. Open the Debug Memory window (View/Debug Windows/Memory). Microsoft Confidential November 2012 5 Hiba! A(z) Heading 2 itt megjelenítendő szövegre történő alkalmazásához használja a Kezdőlap lapot. 4. 5. Type in the variable name. Copy the address of the

variable to the clipboard. 6. 7. 8. Open the Breakpoints dialog. Click on the Data tab. Paste the memory address (preceded with a 0x) The program will break when the variable is modified. The reason we had to use the variable’s memory address as opposed to it’s name, is because the debugger will come to a crawl if you specify a class member or a local variable by name. It doesn’t have a problem with globals though or memory addresses. In this case, you could’ve also just typed in “theApp.m pMainWnd” in the Breakpoints dialog Enterprise and Support Training • Break on an expression. To break when an expression is true, follow steps 1 through 7 above. In step 8, instead of just typing in the memory address of the variable to track, type in an expression including an appropriate cast for the pointer. In the case above, to break if m pMainWnd != NULL, we would enter “*(long)(0x00409AB8)!=0”. • Break on an SDK function. You will need to install the debug symbols

for NT DBG files for NT can be downloaded from http://support.microsoftcom/support/downloads/ These files must be installed in Microsoft Confidential November 2012 6 Hiba! A(z) Heading 1 itt megjelenítendő szövegre történő alkalmazásához használja a Kezdőlap lapot. WINNTSYMBOLSDLL. The DBG files for DLLs installed with IE 4x are in \MOADSSRC. The time stamp for the DLL and DBG files must mactch, otherwise, you’ll see the message in the VC output window of “Loaded C:WINNTsystem32OLEAUT32.DLL, no matching symbolic information found” To verify if the DLL and the DBG match, run DUMPBIN /HEADERS <FILENAME.DLL> DUMPBIN /HEADERS <FILENAME.DBG> You need to know which DLL the function resides in. If you’re not sure, you can run DUMPBIN /EXPORTS <FILENAME.DLL> on each DLL that you suspect it may reside in. For example, SendMessage resides in USER32.DLL Once you know which DLL it’s in, you need to look up the symbolic name in the .DBG file You can do

this by doing a DUMPBIN /SYMBOLS <FILENAME.DBG> The symbolic name will resemble the exported function name. For example, the symbolic name for SendMessage is “ SendMessageA@16”. After finding the symbolic name, you can then type this into the breakpoints window. • at the command-line for each file. The output will include a time stamps and they both must match. • “One or more breakpoints cannot be set and have been disabled. Execution will stop at the beginning of the program”. When you set breakpoints, the Debugger maintains a breakpoints list. When you run the project, the Debugger goes through this breakpoints list and attempts to set the breakpoints based on any symbolic information that is loaded. If there is no symbolic information for the breakpoint, you’ll get the above error. Try checking the following: a) Enterprise and Support Training Make sure youre running the debug version of the program. Microsoft Confidential November 2012 7 Hiba! A(z)

Heading 2 itt megjelenítendő szövegre történő alkalmazásához használja a Kezdőlap lapot. b) Verify what is being loaded and if it has debug symbols. This is shown in VC’s output window. You may be setting code that is in a DLL that is not immediately loaded. To force a DLL to load immediately (along with its symbols file), specify this in Project/Settings in the Debug tab under the "Additional Dlls" category. If breakpoints in MFC source are being disabled, most likely you need to add MFCO42D.DLL or MFC42DDLL c) Make sure the code you’re setting breakpoints on is actually being compiled with your program or loaded. Beware of #ifdefs which exclude code For more information, see Knowledge Base article Q121556 "PRB: Breakpoints Wont Work - 12 Reasons Why". Viewing and Modifying Variables At Runtime • Inspecting function return value. If you’re stepping through a function that doesnt store its return value, you can still see the return value in the

EAX register. For example, to see the value returned from AfxOleInit() in the following function: BOOL InitializeCOM () { return AfxOleInit(); } 1. 2. • Enterprise and Support Training Step into the closing curly brace Open the Registers window and look at the EAX register. Viewing unicode strings. By default unicode strings don’t show up as regular strings in the Watch windows. You can view unicode strings as regular strings in the Watch window by appending “,su” to the variable name. You can also check the “Display unicode strings” checkbox in the Options dialog under Tools/Options in the Debug tab. Microsoft Confidential November 2012 8 Hiba! A(z) Heading 1 itt megjelenítendő szövegre történő alkalmazásához használja a Kezdőlap lapot. • Remember to use the Debug Memory window. The Watch and Variable windows only show up to 256 characters. To view more than 256 characters, use the Debug Memory window. If you’re having trouble viewing a variable

in the Watch windows, you can always count on the Memory window. • Modifying variables at runtime. You can modify variables in the QuickWatch, Watch or Variables window at runtime. This comes in handy when you can’t change the source and you need to change a variable at runtime to see how outcomes differ. • AUTOEXP.DAT To change how a particular data type appears in the Watch windows, open up AUTOEXP.DAT in a text editor It’s located in “Program FilesDevStudioSharedIDEBin”. Documentation is also included in the file Controlling Program Execution Enterprise and Support Training • Take a break. If your program is locked up or you just need to stop your program temporarily, you can select Debug/Break from the DevStudio menu. • Don’t be late. Check “Just-in-Time Debugging” in DevStudio under Tools/Options under the Debug tab. When an application is run outside of DevStudio, and an application error is encountered, you can hit Cancel or Debug to launch the

DevStudio Debugger. This is especially useful if you have a program that works fine when run inside DevStudio but fails outside of it. Microsoft Confidential November 2012 9 Hiba! A(z) Heading 2 itt megjelenítendő szövegre történő alkalmazásához használja a Kezdőlap lapot. • Who’s Next? You can set the next statement to execute by right clicking on the line and picking "Set Next Statement" from the context menu. Use it to quickly verify if certain lines of code are causing a problem by skipping over them. Debug Reporting Functions These functions allow you to send output to a debug window. Unless specified, all functions only work in debug builds( DEBUG is defined). • OutputDebugString. Sends a string to the debugger This function works in both debug and release. • ATLTRACE/AtlTrace(ATL). Supports printf-style formatting and sends output to the debugger by calling OutputDebugString(). • CrtDbgReport. Generates a report with a debugging

message and sends the report to three possible destinations. You can pass a flag to specify how to display a message Flag Behavior CRT WARN message is sent to the debug window CRT ERROR message is displayed in an error dialog CRT ASSERT message is displayed in an assertion dialog You can change the default destinations of these flags with CrtSetReportMode and CrtSetReportFile. Enterprise and Support Training • RPTn (where n is 0, 1, 2, 3, or 4). These five macros send a message string and from zero to four arguments to the report category of your choice. In the cases of macros RPT1 through RPT4, the message string serves as a printf-style formatting string for the arguments. These functions call CrtDbgReport(), and call CrtDbgBreak() if the user clicks on the Retry button. • RPTFn (where n is 0, 1, 2, 3, or 4). Same as RPTn , except that these macros also include in each report the file name and line number at which the macro was executed. • TRACE (MFC).

Provides similar functionality to the printf function by sending a formatted string to a dump device such as a file or debug monitor. It does this by sending output to a CDumpContext object called afxDump. Unless output is to a file, TRACE eventually ends up calling CrtDbgReport( CRT WARN,). TRACE is Microsoft Confidential November 2012 10 Hiba! A(z) Heading 1 itt megjelenítendő szövegre történő alkalmazásához használja a Kezdőlap lapot. limited to sending a total of 512 characters at a time. When debugging Unicode, the TRACE0, TRACE1, TRACE2, and TRACE3 macros are easier to use because the T macro is not needed. This feature needs to be turned on by checking “Enable tracing” checkbox in the “MFC Tracer” tool. For more information, see Subject MFC Technote 7: Debugging Trace Options • Rerouting TRACE messages to a file. You can reroute MFC trace messages to a file. This would be useful if the program only fails on a non-development machine TRACE() in MFC

sends output to a CDumpContext object called afxDump. CDumpContext has a Cfile member called m pFile that we can set. As an example, you can add the following lines: CFile fileDump ("test.log", CFile::modeCreate|CFile::modeNoTruncate|CFile::modeWrite); BOOL CTestApp::InitInstance() { afxDump.m pFile = &fileDump; } For this to work on a non-development machine, you’ll need to ship the debug version of the program. You’ll also need to enable tracing using the MFC Tracer tool and copy the AFX.INI file into the Windows or Winnt directory Enterprise and Support Training • Writing to a log file in both release and debug builds. To write out a log file in both debug and release builds, you can use printf() in your code. Pass a command-line argument of “>filename” when running the program. This sets up the file you passed in as stdout. • DBMON.EXE Debug Monitor works only under NT and comes with the Platform SDK. On machines where no debugger is installed,

this can be used to test debug builds. Any output meant for the debug window will appear here Microsoft Confidential November 2012 11 Hiba! A(z) Heading 2 itt megjelenítendő szövegre történő alkalmazásához használja a Kezdőlap lapot. • DBWIN.EXE Windows Debug Monitor also comes with the Platform SDK It’s similar to DBMON except that it’s a windows app and it only works under Windows 95. Debug Validation Functions These functions check if a particular expression is true and displays an error dialog if it isn’t. Unless specified, all functions only work in debug builds( DEBUG is defined) Keep in mind that any code enclosed within these assert functions will not be compiled in release builds. • ASSERT. If an expression evaluates to false, this macro calls CrtDbgReport( CRT ASSERT,) to display an assertion dialog. It also calls CrtDbgBreak() if the user clicks on the Retry button. • ASSERTE. Same as ASSERT, except that it also reports a string

representation of the expression that evaluated to false • ASSERT (MFC). Same as ASSERT • ASSERT VALID (MFC). Validates a CObject-derived pointer, checks against NULL, and calls the objects own AssertValid member functions. If any of these tests fails, this displays an alert message in the same manner as ASSERT. • VERIFY (MFC). Same as ASSERT, except that this is the only assertion type function that still compiles the expression in release builds. You still won’t get an assertion dialog in release builds if the expression fails. Memory Diagnostic Functions • Detecting a memory leak. Try calling CrtDumpMemoryLeaks() at the end of your program. You can also take snapshots of the heap at 2 different locations and do a comparison: 1. Create 3 CrtMemState structures 2. Call CrtMemCheckpoint() passing the first CrtMemState struct This takes a snapshot of the heap. 3. When you get to a point where you want to see if the heap is as it was when you took the snapshot,

call CrtMemCheckpoint() again passing the second CrtMemState struct. 4. Check for a difference by calling CrtMemDifference() passing all 3 CrtMemState structures. The first one will contain the difference 5. You can dump its contents by calling CrtDumpStatistics() The finished code might look something like the following: Enterprise and Support Training Microsoft Confidential November 2012 12 Hiba! A(z) Heading 1 itt megjelenítendő szövegre történő alkalmazásához használja a Kezdőlap lapot. CrtMemState s1, s2, s3; CrtMemCheckpoint( &s1 ); // do memory allocations here CrtMemCheckpoint( &s2 ); if ( CrtMemDifference( &s3, &s1, &s2 ) ) CrtMemDumpStatistics( &s3 ); You can accomplish the same thing in MFC using the following steps. 1. Create a CMemoryState object and call the Checkpoint member function to get the initial snapshot of memory. 2. After you perform the memory allocation and deallocation operations, create another

CMemoryState object and call Checkpoint for that object to get a current snapshot of memory usage. 3. Create a third CMemoryState object, call the Difference member function, and supply the previous two CMemoryState objects as arguments. The return value for the Difference function will be nonzero if there is any difference between the two specified memory states, indicating that some memory blocks have not been deallocated. • Finding the source of a memory leak. Call CrtDumpMemoryLeaks() to get a list of memory leaks with their allocation numbers. The allocation number is the one within {}. MFC will automatically call CrtDumpMemoryLeaks() when a debug program shuts down. You can break on the memory allocation by calling CrtSetBreakAlloc() passing the allocation number. If you don’t want to change the source and recompile you can also set the global variable crtBreakAlloc: 1. Choose Step Into from the Build/Debug menu 2. Open the Watch window 3. If you are statically

linking to the C runtime, type in crtBreakAlloc and set it’s value to the allocation number. If you are dynamically linking to the C runtime, type in “{,,msvcrtd.dll}* p crtBreakAlloc()” and set it’s value to the allocation number. The program will break when this allocation number is being created (new/malloc is called). For more information, see Knowledge Base article Q151585 "HOWTO: Use crtBreakAlloc to Debug a Memory Allocation". • CrtDumpMemoryLeaks. Dumps all of the memory blocks in the debug heap when a memory leak has occurred. MFC’s AfxDumpMemoryLeaks() calls this function. • CrtMemDumpStatistics. Dumps the debug header information for a specified heap state in a user-readable form. Called by MFC’s CMemoryState::DumpStatistics(). • CrtMemCheckPoint. Obtains the current state of the debug heap and stores in an application-supplied CrtMemState structure. Called by MFC’s CMemoryState::Checkpoint(). • CrtMemDifference. Compares two

memory states and returns their differences Called by MFC’s CMemoryState::Difference(). • CrtCheckMemory. Confirms the integrity of the memory blocks allocated in the debug heap. MFC’s AfxCheckMemory() calls this function • CrtIsValidHeapPointer. Verifies that a specified pointer is in the local heap • Enterprise and Support Training CrtIsValidPointer. Verifies that a specified memory range is valid for reading and writing . Microsoft Confidential November 2012 13 Hiba! A(z) Heading 2 itt megjelenítendő szövegre történő alkalmazásához használja a Kezdőlap lapot. • CrtSetAllocHook. Installs a hook function that gets called whenever new/delete or malloc/free are called. Similar to MFC’s AfxSetAllocHook() • CrtSetBreakAlloc. Sets a breakpoint on a specified object allocation order number by new or delete. • CrtSetDbgFlag. Retrieves and/or modifies the state of the crtDbgFlag flag to control the allocation behavior of the debug heap

manager. afxMemDF in MFC is defined as crtDbgFlag. Some useful flags are: Flag • Description CRTDBG ALLOC MEM DF Enable debug heap allocations and use of memory block type identifiers, such as CLIENT BLOCK. Equivalent to allocMemDF in MFC. CRTDBG CHECK ALWAYS DF Call CrtCheckMemory() at every allocation and deallocation request. Equivalent to checkAlwaysMemDF in MFC. CRTDBG LEAK CHECK DF Perform automatic leak checking at program exit via a call to CrtDumpMemoryLeaks() and generate an error report if the application failed to free all the memory it allocated. STRESS.EXE You can use STRESSEXE on Windows 95 to monitor memory and resource usage. Tracking Down GPFs/Exceptions • Breaking on instruction that caused exception. If you get an unhandled exception dialog with a memory location, you can set a breakpoint on that memory location, by going into the breakpoints dialog and typing in the memory address in the Location tab. If it only happens in release, build the

Release target with debug information. • NT and Win95 debug symbols. If the exception points to a system DLL, install the NT or Win95 debug symbols and look at the call stack when you get the exception. For more information, see Knowledge Base article Q148659 "How to Set Up Windows NT Debug Symbols". For more information, see Knowledge Base article Q148660 "How to Verify Windows NT Debug Symbols". For more information, see Knowledge Base article Q141465 "How to Install Symbols For Dr. Watson Error Debugging" Enterprise and Support Training Microsoft Confidential November 2012 14 Hiba! A(z) Heading 1 itt megjelenítendő szövegre történő alkalmazásához használja a Kezdőlap lapot. For more information, see Knowledge Base article Q133174 "How to Locate Where a General Protection (GP) Fault Occurs". Works In Debug But Not In Release Enterprise and Support Training • 1. 2. Turn off optimization(/Od). Select Project/Settings

from the menu and click on the C++ tab. Select Disable from the Optimizations drop-down list. • 1. 2. Build Release target with debug info. Select Project/Settings and click on the Link tab. Check “Generate debug info”. Microsoft Confidential November 2012 15 Hiba! A(z) Heading 2 itt megjelenítendő szövegre történő alkalmazásához használja a Kezdőlap lapot. 3. Click on the C/C++ tab and select “Program Database” under “Debug info”. 4. Build and run the Release version of the project under the debugger. The debugger may break at the specific line that is causing a problem. • Enterprise and Support Training Use WINDBG.EXE This program comes with the Platform SDK If no debugger is installed on a machine, this program can be used instead. It’s not as full featured as DevStudio but has a lot of the options you need to track down bugs. It lets you set different types of breakpoints, inspect variables, memory, etc. Microsoft Confidential November

2012 16 Hiba! A(z) Heading 1 itt megjelenítendő szövegre történő alkalmazásához használja a Kezdőlap lapot. COM Debugging • Stepping into a Local Server from the client. If you try to step into a method in your local server from the client, you won’t be able to unless you have “OLE RPC Debugging” checked in the Debug tab under Tools/Options. DevStudio will automatically launch an instance of itself and start debugging the server. • 1. 2. 3. 4. Enterprise and Support Training Debugging Local Automation Servers. Go into Project/Settings under the Debug tab. Set “Program arguments” to “/Automation”. Set your breakpoints and run the project. Start the client from either another instance of DevStudio or from Windows Explorer. The client will connect to the running instance of the server Microsoft Confidential November 2012 17 Hiba! A(z) Heading 2 itt megjelenítendő szövegre történő alkalmazásához használja a Kezdőlap lapot. • 1. 2. 3.

4. Debugging Embedding or DocObject Servers. Go into Project/Settings under the Debug tab. Set “Program arguments” to “/Embedded”. Set your breakpoints and run the project. Start the container from either another instance of DevStudio or from Windows Explorer. Insert an instance of the server and you will be connected to the running instance. For more information, see Knowledge Base article Q154116 "HOWTO: Debug OLE Applications". Enterprise and Support Training Microsoft Confidential November 2012 18 Hiba! A(z) Heading 1 itt megjelenítendő szövegre történő alkalmazásához használja a Kezdőlap lapot. • Breakpoints are not hit for Local Automation, Embedding or DocObject servers. Use Task Manager or PView to verify that there’s only one instance of the server running. The client/container may be connecting to a difference instance of the server that is not running under the Debugger. • Debugging DCOM Servers. Debugging DCOM servers is just

like debugging a local automation server except that the Debugger and server are running on one machine, while the client is running in another: 1. Go into Project/Settings under the Debug tab 2. Set “Program arguments” to “/Automation” 3. Set your breakpoints and run the project 4. Start the client from the other machine The client will connect to the running instance of the server on the other machine. If the debugger is not available on the machine where the server is running, you can also setup a remote debugging session. Instructions for doing this are in the latter part of this document. • Debugging ActiveX controls and Shell Extensions in IE 4. IE 4 is a singleinstance app A new thread is launched instead of a new process whenever you run IEXPLORE.EXE or EXPLOREREXE This prevents the debugger from attaching to it when you specify it as the debug executable. You can get around this by doing the following: 1. Enterprise and Support Training Set the debug executable

to IEXPLORE.EXE Microsoft Confidential November 2012 19 Hiba! A(z) Heading 2 itt megjelenítendő szövegre történő alkalmazásához használja a Kezdőlap lapot. 2. Force a new instance of EXPLORER.EXE by specifying a Program Argument of – new. Another method is documented in Q167715. For more information, see Knowledge Base article Q167715 "HOWTO: Debugging ActiveX Controls in IE 4.0 Browser" For more information, see Knowledge Base article Q138942 "HOWTO: Debug a Windows Shell Extension". • Debbugging Microsoft Transaction Server(MTS) Components. For more information, see Knowledge Base article Q172869 "HOWTO: Debug a Component Written with Visual Basic 5.0" For more information, see Knowledge Base article Q166275 "HOWTO: Debug a Native Code Visual Basic Component in VC++". • Debugging Active Server Page(ASP) Components. For more information, see Knowledge Base article Q166275 "HOWTO: Debug a Native Code Visual Basic

Component in VC++". For more information, see Knowledge Base article Q152054 "INFO: Tips for Debugging ISAPI DLLs". For more information, see Subject MFC Technote 63: Debugging Internet Extension DLLs • Enterprise and Support Training Tracking QueryInterface() calls. Let’s say you have an ActiveX control on a container and the control doesn’t appear. You’re not getting any errors Where do you start? In this case, looking at what interfaces your control is queried for, might give you a clue as to what the last function the container tried to call on the control before it failed. In ATL, if you #define ATL DEBUG QI before including ATLCOMH, this brings in an implementation of QueryInterface() that sends output to the debugger window for all known interfaces that are queried for. With MFC, you can override Microsoft Confidential November 2012 20 Hiba! A(z) Heading 1 itt megjelenítendő szövegre történő alkalmazásához használja a Kezdőlap lapot.

CCmdTarget::GetInterfaceHook() and print the interface name. AfxGetIIDString() is a helper that returns the interface name. GetInterfaceHook() is called whenever QueryInterface() is called: LPUNKNOWN CTestCtrl::GetInterfaceHook(const void* piid) { #ifdef DEBUG LPCTSTR strIID = AfxGetIIDString(*(IID)(piid)); TRACE("QueryInterface() REFIID = %s ", strIID); #endif return COleControl::GetInterfaceHook (piid); } Tip You can actually override CCmdTarget::GetInterfaceHook() globally. This would come in handy if you wanted to see all QueryInterface() calls in your program (e.g container or embedding server). Just implement CCmdTarget::GetInterfaceHook() in your project and use the /force compiler switch to ignore the multiply-defined linker error. • Tracking AddRef() and Release() calls. There may be times when tracking an object’s refcount is useful. In ATL, you can #define ATL DEBUG REFCOUNT and AddRef/Release calls send output to the debug window, including the current

refcount. Achieving the same result in MFC is not as simple You would need to override CCmdTarget’s implementation of AddRef() and Release(). The HOOKCTRL sample in the knowledge base shows how to do this. For more information, see Knowledge Base article Q179689 "FILE: Hooking into the IUnknown of a COM Object in MFC". Miscelaneous Enterprise and Support Training • Debugging Services. Steps for debugging a service: 1. Double-click on Services in Control Panel. 2. Double-click on the service you want to debug 3. Check “Allow Service to Interact with Desktop”. If you don’t check this, the service will appear to hang when an ASSERT or message box is encountered. Microsoft Confidential November 2012 21 Hiba! A(z) Heading 2 itt megjelenítendő szövegre történő alkalmazásához használja a Kezdőlap lapot. 4. Click on the Start button to start the service. 5. From the DevStudio menu select Build/Start Debug/Attach to Process. 6. Check the

“System Processes” checkbox to display your service. 7. Double-click on the service to load it into the Debugger. 8. From the DevStudio menu, select Debug/Break. 9. Open your source files and set your breakpoints. 10. If the service is an automation server, start the client and call into the service Your breakpoints will be hit. Enterprise and Support Training Microsoft Confidential November 2012 22 Hiba! A(z) Heading 1 itt megjelenítendő szövegre történő alkalmazásához használja a Kezdőlap lapot. For more information, see Knowledge Base article Q170738 "Debugging a Windows NT Service". For more information, see Knowledge Base article Q98890 "HOWTO: Debugging a service". • Remote Debugging. Remote debugging allows you to run the debugger in one machine and the Exe to debug in another. This is handy if no debugger is installed on the machine and the problem only happens on machines where DevStudio is not installed. You can also debug

DCOM servers this way Steps for remote debugging: On the Remote Machine, do the following: 1. Copy MSVCMONEXE, MSVCRTDLL, TLN0TDLL, DMDLL, MSVCP50DLL and MSDIS100.DLL to a shared directory on the remote machine If the remote machine is NT 4.0, you also need to copy PSAPIDLL All these files are already there if VC++ 5.0 is installed on the remote machine 2. Copy the debug build of the Exe that you want to debug 3. Run MSVCMONEXE 4. Click on the “Settings” button and type in the host machine name. 5. Click on the “Connect” button. You’ll see a dialog entitled “Connecting” with a button labeled “Disconnect”. The dialog will remain this way until you connect a debugger from another machine. On the Host Machine, do the following: 1. Load the Exe project and set your breakpoints accordingly Enterprise and Support Training Microsoft Confidential November 2012 23 Hiba! A(z) Heading 2 itt megjelenítendő szövegre történő alkalmazásához használja a Kezdőlap

lapot. Enterprise and Support Training 2. 3. From the menu, select Build/Debugger Remote Connection In the “Remote Connection” dialog, select “Network (TCP/IP)”. 4. In the “Remote Connection” dialog, click on the Settings button and type in the remote machine name. 5. 6. From the menu, select Project/Settings and click on the Debug tab. Under “Remote executable path and file name”, type in the remote path of the .Exe (e.g \samsontpublic estexe) Microsoft Confidential November 2012 24 Hiba! A(z) Heading 1 itt megjelenítendő szövegre történő alkalmazásához használja a Kezdőlap lapot. 7. Run the project. The UI should appear on the remote machine For more information, see Knowledge Base article Q131058 "INFO: Tips for Remote Debugging with Visual C++". • Tracking dependencies. You can find out what the dependent DLLs are for a module by using one of the following tools: 1. DEPENDSEXE (not the diaper) This program comes with the

Platform SDK Enterprise and Support Training Microsoft Confidential November 2012 25 Hiba! A(z) Heading 2 itt megjelenítendő szövegre történő alkalmazásához használja a Kezdőlap lapot. 2. Enterprise and Support Training DUMPBIN.EXE This program comes with VC++ Run it with the /DEPENDENTS switch. • APIMON.EXE Another useful tool from the Platform SDK This program tracks all calls in a program and spits this out in a window. It uses the export table in DLLs to list a function name. Unfortunately, since MFC exports everything by ordinals, you’ll only see ordinal numbers in APIMON for MFC functions. • Debugging Multithreaded Apps. DevStudio allows you to Suspend, Resume and Set Focus to a thread. While debugging an application, from the menu select Debug/Threads to bring up the debug Threads dialog. Suspending other threads may come in handy when you have a hanging problem. Seting focus to a thread before doing a Debug/Break may come in handy as well.

Microsoft Confidential November 2012 26 Hiba! A(z) Heading 1 itt megjelenítendő szövegre történő alkalmazásához használja a Kezdőlap lapot. New debugger features in Visual C++ 6.0 AfxDumpStack for Diagnosing Field-Installed Applications. The AfxDumpStack function generates an image of the current stack and dumps that image to the debug output device (for example, afxDump). This feature provides a mechanism with which you can get diagnostic information even if the debugger is not installed on the end users machine. It can be used in debug and non-debug versions of the MFC libraries Edit and Continue. Edit and Continue allows you to incorporate common, simple edits during a debugging session without having to quit the session, rebuild, and restart the debugger. Changes are recompiled and applied to the executing application in memory GetLastError() Value Displayed as Register. This is a new pseudo-register called ERR that displays the last error for the current thread.

This pseudo-register is not an actual hardware register, but is displayed as though it were a hardware register. It retrieves the same value as calling the GetLastError function. Using it in conjunction with the ,hr modifier produces very useful output, showing the error message corresponding to each error code. If this register is not found, you should prefix this register with an @ sign. GUIDs Decoded for Display. Types based on GUIDS (including IIDs, CLSIDs, and REFIIDs) are displayed by name (if found in the registry), or failing that, in the normal GUID hex form. Improved Disassembler Output (Undecorated Symbols). The disassembly window and callstack window now undecorate C++ names where they did not before, such as when displaying system callstacks from Windows NT DBG files. You now see the C++ name with a proper argument list. Improved V-Table and Function Pointer Display. Pointers to functions and v-table entries are now displayed symbolically wherever possible, including

parameters. Previously, these items were displayed as just hex addresses in Visual C++ 5.0 In-Process Remote Procedure Calls. RPC debugging now works with in-process remote procedure calls (RPCs), as well as out-of-process RPCs. Load COFF & Exports Option. The new Load COFF & Exports option allows additional debugging information to be loaded when the standard CodeView format debugging information is not available. This option enables you to see some useful symbols in the call stack even when CodeView debug information is not available. This option is useful for seeing window messages, for WindowProcs and COM objects, and when marshalling is involved. Module List Dialog Box. This new dialog box displays the address, name, path, and load order for all DLLs used by your program. You can use this dialog box to determine which DLL your program crashed in. Enterprise and Support Training Microsoft Confidential November 2012 27 Hiba! A(z) Heading 2 itt megjelenítendő

szövegre történő alkalmazásához használja a Kezdőlap lapot. New Formatting Symbols. The following are new symbols for Watch windows: hr, st, mq, wm, and wc. Thread Information Block. This is a new pseudo-register that displays the Thread Information Block (TIB, also known as a TEB) for the current thread. If this register is not found, you should prefix this register with an @ sign. For more information on the content of TIBs, see "Under the Hood," Microsoft Systems Journal May 96. Variants Decoded for Display. Variants are automatically displayed in their correct form: integers are displayed numerically, BSTRs as strings, and so on. The type of the variant is also displayed. Enterprise and Support Training Microsoft Confidential November 2012