Debugging skills for 10 native Visual Studio development

Source: Internet
Author: User
Tags visual studio 2010
10 even more Visual Studio debugging tips for Native Development

Original Chinese address: http://www.oschina.net/translate/10-even-more-visual-studio-debugging-tips-for-native? From = 20130127



My previous articles on Visual Studio debugging skills have aroused great interest, so I decided to share more debugging knowledge. In the following list, you can see the Native Development debugging skills (followed by previous articles ). These skills can be applied to vs2005 or later versions (of course some of them can be applied to earlier versions ). If you continue, you can learn the details of each technique.

  1. Data breakpoint
  2. Thread rename
  3. Specific process interruption
  4. Approximate execution time
  5. Number formatting
  6. Memory data formatting
  7. System DLL interruption
  8. Load symbol table
  9. Memory leakage report in MFC
  10. Debug ATL

Tip 11: Data breakpoint

When the memory location of the data changes, the debugger will interrupt. However, this is the only way to create a data breakpoint for a hardware such as 4 at a time. Data breakpoints can only be added during compilation. You can use the menu (compile> New breakpoint> new data breakpoint) or the breakpoint window to add data breakpoints.



You can use a memory address or address expression. Even if you can see two values on the stack, I think this function is useful when the value on the stack is changed. This helps identify memory corruption.



In the following example, the pointer value has been changed to the object value. To find out where the changes are made, I set a breakpoint at the position of the pointer value storage, such as & PTR (note that this occurs after the pointer is initialized ). When the data is changed, the debugger terminates when someone changes the pointer value and then finds out which code has caused the change.


Additional reading:

  • How can I find out if my pointers has upt a memory address?
  • How can I find out where my pointer is getting changed?

Tip 12: rename a thread

When you debug a multi-threaded application, the threads window displays the created threads and the current threads. The more threads you need, the more difficult you will find the thread you are looking for (especially when the same program is executed by multiple threads at the same time, you do not know which thread instance is being executed)


The debugger allows you to rename a thread. Right-click a thread and rename it.


You can also name a thread in programming mode. Although this is tricky and must be done after the thread starts, otherwise the debugger will reinitialize it with its default naming rules, the following functions show how to define and use a thread.


typedef struct tagTHREADNAME_INFO
{
DWORD dwType; // must be two bytes in length
LPCSTR szName; // pointer to name (same address space)
DWORD dwThreadID; // Thread ID (-1 calling thread)
DWORD dwFlags; // Reserved for future use, 0 in most cases
} THREADNAME_INFO;

void SetThreadName (DWORD dwThreadID, LPCSTR szThreadName)
{
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = szThreadName;
info.dwThreadID = dwThreadID;
info.dwFlags = 0;

__try
{
RaiseException (0x406D1388, 0, sizeof (info) / sizeof (DWORD), (DWORD *) & info);
}
__except (EXCEPTION_CONTINUE_EXECUTION)
{
}
}


Tip 13: Specify the thread to set the breakpoint

Another useful technique for Multithreaded Applications is to set breakpoints on specified threads, processes, and even computers. You can use the breakpoint filer command to implement this function.


The debugger allows you to use different combinations of thread name, thread ID, process name, process ID, and machine name (using and, or, not connection ). Mastering how to set the thread name makes this filtering technique easier.

Secondary reading:

  • How to: specify a breakpoint Filter
  • Setting a breakpoint Filter

Tip 14: (inaccurate) scheduled execution

In my previous article, I mentioned using pseudo variables in the watch window. One of the unmentioned ones is @ CLK, which displays the value of a counter to obtain the approximate time required for code execution between two breakpoints, in milliseconds (MS ). However, this method cannot be used for configuration program execution. You should use Visual Studio profiler or performance timer to complete these configurations.

Reset the timer by adding @ CLK = 0 in the watch window or immediate window. Therefore, if you need to calculate the time required for the last code execution, do the following:

  • Set a breakpoint at the beginning of a code block
  • Set a breakpoint at the end of the code block
  • Add @ CLK in the watch window
  • When the first breakpoint is triggered, enter @ CLK = 0 in the intermediate window.
  • Run the program until the breakpoint at the end of the code block is reached, and view the value of @ CLK in the watch window.

Note that you need to add two expressions in the watch window: @ CLK and @ CLK = 0. It is said that the timer can be reset at the position where the breakpoint is executed each time. This technique can only be used in earlier versions of Visual Studio, but cannot be used in later versions of Visual Studio, such as vs2005 (tested by the author and not supported by vs2005) and later versions.

Secondary reading:

  • Debugging tips-@ CLK

Tip 15: format the number

When you use the watch or quick Watch window to view variables, these values are displayed in the default predefined visual format. When a variable is a number, it is displayed in decimal format according to its type (INT, float, double. However, you can set the debugger to use different types for displaying numbers, or use different hexadecimal values.

To change the display type of a variable, you can add the following prefix before the variable:

  • By -- unsigned char (unsigned byte)
  • Wo -- unsigned short (unsigned word)
  • DW -- unsigned long (unsigned double word)

You can add the following prefix before the variable to change the OS:

  • D Or I -- signed decimal number
  • U -- unsigned decimal number
  • O -- unsigned octal number
  • X -- lowercase hexadecimal number
  • X -- uppercase hexadecimal number


Secondary reading:

  • C ++ debugger tips
  • Tip 16: Format memory data

    In addition to numbers, debugger can also display formatted memory data in the watch window, up to 64 bytes. You can add the following suffix after the expression (variable or memory address) to format the data:

    • MB or M-hexadecimal 16-byte data, followed by 16 ASCII characters
    • MW -- 8 words (word, usually 1 word = 2 byte) data
    • MD -- four dual-words (DWORD, usually 1 DWORD = 4 byte) data
    • MQ -- two four-character (quad word) data
    • Ma -- 64 ASCII characters
    • Mu -- 2-byte Unicode Character


    Additional reading:

    • Format specifiers in C ++
    • Debugging tips in developer Studio

    Tip 17: Pause the system DLL call.

    Sometimes it is useful to pause a function of a DLL when it is called, especially system DLL (such as kernel32.dll and user32.dll ). To implement this pause, you must use the context operator provided by native debugger. You can set the breakpoint location, variable name, or expression:

    • {[Function], [Source Code], [module]} breakpoint location
    • {[Function], [Source Code], [module]} variable name
    • {[Function], [Source Code], [module]} expressions

    The braces can be any combination of the function name, source code, and module, but the comma cannot be omitted.

    For example, if we need to pause the createthread function call. This function is exported from kernel32.dll, so the context operator should be like this: {, kernel32.dll} createthread. However, this is not the case because the operator requires the name after createthread. Available

    Dbh.exe to get the modifier of a specific function (compiled by the compiler ). The following describes how to get the createthread modifier:

    C:\Program Files (x86)\Debugging Tools for Windows (x86)>dbh.exe -s:srv*C:\Symbo
    ls*http://msdl.microsoft.com/Download/Symbols -d C:\Windows\SysWOW64\kernel32.dl
    l enum *CreateThread*
    Symbol Search Path: srv*C:\Symbols*http://msdl.microsoft.com/Download/Symbols
    
     index            address     name
         1            10b4f65 :   _BaseCreateThreadPoolThread@12
         2            102e6b7 :   _CreateThreadpoolWork@12
         3            103234c :   _CreateThreadpoolStub@4
         4            1011ea8 :   _CreateThreadStub@24
         5            1019d40 :   _NtWow64CsrBasepCreateThread@12
         6            1019464 :   ??_C@_0BC@PKLIFPAJ@SHCreateThreadRef?$AA@
         7            107309c :   ??_C@_0BD@CIEDBPNA@TF_CreateThreadMgr?$AA@
         8            102ce87 :   _CreateThreadpoolCleanupGroupStub@0
         9            1038fe3 :   _CreateThreadpoolIoStub@16
         a            102e6f0 :   _CreateThreadpoolTimer@12
         b            102e759 :   _CreateThreadpoolWaitStub@12
         c            102ce8e :   _CreateThreadpoolCleanupGroup@0
         d            102e6e3 :   _CreateThreadpoolTimerStub@12
         e            1038ff0 :   _CreateThreadpoolIo@16
         f            102e766 :   _CreateThreadpoolWait@12
        10            102e6aa :   _CreateThreadpoolWorkStub@12
        11            1032359 :   _CreateThreadpool@4


    It looks like the real name is _ createthreadstub @ 24. Therefore, we can create breakpoints,{, Kernel32.dll} _ createthreadstub @ 24.

    When a program is paused, the message about no source code at the breakpoint is directly ignored.

     

    Use the call Stack window to view the code for calling this function.

     

    Additional reading:

    • How to set breakpoints without source code in Visual Studio 2010
    • Context operator (C/C ++ language expressions)
    • How to: Set a function breakpoint

    Tip 18: load the symbol

    When you debug a program, the call Stack window may not display all call stacks, ignoring the information of system DLL (such as kernel32.dll and user32.dll.



    By loading the DLL symbolic information, you can obtain all call stack information. In the call Stack window, you can use the context menu (right-click menu) to directly set this effect. You can download these symbols from a predefined symbolic path or Microsoft's symbolic server (for system DLL. After these symbols are downloaded and imported to the debugger, the call stack is updated as follows:

     

    These symbols can also be imported from the Module window.


    Once loaded, these symbols are saved in the cache and can be configured in tools> Options> debugging> symbols.


    In the source code generated by the MFC wizard, the # include post-mina contains the following pre-processing commands:


    #ifdef _DEBUG
    #define new DEBUG_NEW
    #endif

    The code above is how to redefine the new operator.


    Many STL header files are incompatible with the new operator defined here. If you include header files such as <map> <vector> <list> <string> after the new operator, the following error occurs (take <vector> as an example ):


    1>c:\program files (x86)\microsoft visual studio 9.0\vc\include\xmemory(43) : error C2665: 'operator new' : none of the 5 overloads could convert all the argument types
    1>        c:\program files\microsoft visual studio 9.0\vc\include\new.h(85): could be 'void *operator new(size_t,const std::nothrow_t &) throw()'
    1>        c:\program files\microsoft visual studio 9.0\vc\include\new.h(93): or       'void *operator new(size_t,void *)'
    1>        while trying to match the argument list '(const char [70], int)'
    1>        c:\program files (x86)\microsoft visual studio 9.0\vc\include\xmemory(145) : see reference to function template instantiation '_Ty *std::_Allocate<char>(size_t,_Ty *)' being compiled
    1>        with
    1>        [
    1>            _Ty=char
    1>        ]
    1>        c:\program files (x86)\microsoft visual studio 9.0\vc\include\xmemory(144) : while compiling class template member function 'char *std::allocator<_Ty>::allocate(std::allocator<_Ty>::size_type)'
    1>        with
    1>        [
    1>            _Ty=char
    1>        ]
    1>        c:\program files (x86)\microsoft visual studio 9.0\vc\include\xstring(2216) : see reference to class template instantiation 'std::allocator<_Ty>' being compiled
    1>        with
    1>        [
    1>            _Ty=char
    1>        ]


    The solution is to use debug_new to redefine the new operator after including these STL files.

    Additional reading:

    • Debug_new

    Tip 20: Debug ATL

    When developing the atl com component, you can view the QueryInterface, addref, and release calls of the COM object in the debugger. By default, these calls are not supported. You need to define two Macros in the pre-processing definition or pre-compilation header file. After these two macros are defined, the call to these functions will be displayed in the output window.

    The two macros are:

    • _ Atl_debug_qi,Displays the name of each interface to be queried. It must be defined before the atlcom. h header file is included.
    • _ Atl_debug_interfaces,When addref or release is called, it displays the number of times the current interface is referenced, the class name, the interface name, and other information. It must be defined before atlbase. H is included.

    Secondary reading:

    • Debugging tips
    • ATL Debugging techniques
    • How does _ atl_debug_interfaces work?

    Conclusion

    Tips mentioned in this article and the previous article does not include all debugging skills, but it can help you solve most of your native application problems.


    Related Article

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.