Debugging Policy
Chapter 1 debugging process
1. The key to successful and efficient debugging is to find accurate error information.
2. Once an error is found, more may be found. Similar code may have similar errors.
3. Learn how to prevent future errors from mistakes
4. For the new code, you do not need to perform a test to determine whether it has any errors.
Chapter 2 compile C ++ code for debugging
C ++ language and programming style
1. Use advanced features of the language as needed
2. To write code that can be understood by "people", not only the Compiler
3. Use the Hungarian naming convention with caution
4. Each statement line should be used as a separate atomic unit, so that the debugging tool can be fully utilized.
5. If you are not sure whether parentheses are required, you need parentheses.
6. Use the C ++ features to prevent errors:
Use const instead of # define to create constants;
Use Enum instead of # define to create a constant set;
Replace # define macro with the inline function;
Replace malloc and free with new and delete;
Replace standard I/O with I/O streams.
7. redeclare all shared external symbols in the header file and retain the parameter names in the original function for ease of understanding.
8. The release version is often created to help check uninitialized variables, because the optimizer checks the usage of variables.
9. Use the maximum/small value in limits. h as the size limit of the integer data type. The maximum/small value of the floating point type is defined in float. h.
10. In VC ++, the character type is signed by default [-128 ~ 127]
11. Do not use forced type conversion unless necessary
Dynamic_cast: used for converting polymorphism (rtti of the compiler must be enabled)
Static_cast: used for non-polymorphism type conversion
Const_cast: used to remove the const, volatile, and _ unaligned (x64) attributes.
Reinterpret_cast: used to convert incompatible data types, such as pointers and non-pointers.
12. Use const carefully in the program to discover more errors during compilation
13. Do not add const after the program is completed. Use const correctly and strictly at the beginning.
14. If you need to increase or decrease the variable for each loop, use for instead of while
15. methods for handling constructors that may encounter errors:
1. Perform basic initialization without errors in the constructor, and perform initialization operations that may be wrong in another function (init.
Ii. Use the exception mechanism to capture exceptions during initialization, release initialized resources (you can also use the auto_ptr smart pointer), and throw an exception
16. If a destructor is called when an exception is handled, and The Destructor generates an unprocessed exception, the program will be terminated. Because the exception thrown during stack expansion will terminate the entire program
17. Due to the reason described in No. 16, exceptions in the Destructor must be processed in the destructor.
18. If a class requires a destructor to release the resources allocated by the constructor, either copy the constructor and assign value operators or use private to prevent them from being automatically added
19. "": If a class requires an destructor, a copy constructor, or a copy operator, all three of them need
Visual c ++ Compiler
1. Always use/W4 Warning Level
2. Use the/GZ option in the debugging version to help you find errors that can only be found in the release version.
3. Use # pragma warnning to control and adjust specific warnings (for details, see the VC ++ documentation). When using # pragma, it is best to give a clear comment.
4. Check the cause carefully when eliminating the compilation warning. It is not a direct cause, but a hidden root cause of the warning. The final goal is to eliminate errors rather than warnings.
Chapter 3 Use assertions
1. assertions can only be used to check validity, not correctness
2. Maintain the simplicity of assertions. Good coverage
3. When using assertions in the C Language Runtime Library, use _ asserte instead of _ assert; when using the MFC Library, use assert macro
4. Using atlassert In The Atl program allows you to use custom assertions.
5. Verify is generally used to detect the return values of Windows APIs (we recommend that you use assert instead of verify macro)
6. Call the assert_valid macro before using the cobject class's derived class Object
7. Public functions require more comprehensive assertions than private and protected Functions
8. Make clear comments for those assertions that are not so obvious
9. No spam input should cause spam output.
Chapter 4 Use trace statements
1. Windows API: outputdebugstring function, which can be run in debug/release versions. It is suitable for tracking start/end
2. C runtime of VC ++: _ rptn and _ rptfn series Functions
3. Trace (n) in MFC ):
Afxoutputdebugstring macro: the debugging version is medium to _ rpt0, And the release version is medium to outputdebugstring.
Cobject: dump function:
Afxdump global object:
Afxdumpstack function:
4. ATL trace statements: atltrace and atltrace2 Functions
Chapter 5 use exceptions and return values
1. Do not use exception handling to block errors that cannot be re-obtained
2. Exceptions are raised and handled based on each thread, but unhandled exceptions will end the entire process.
3. Exception Handling requires a lot of additional operations, so it is not suitable for frequently Running code.
4. The frequent occurrence may not be a real error.
5. return values (rather than exceptions) are applicable in the following situations ):
Used to indicate non-error status information
Used for errors that can be ignored without any problems in most cases.
Used for errors that are easier to appear in loops (Exceptions require additional overhead)
Used for errors in the intermediate language module, such as com
6. You must use the/EHA debugger option to capture operating system exceptions using the C ++ exception mechanism.
7. You can use the _ set_se_translator function to install a converter that converts se to C ++ exception for a thread.
8. Only floating point overflow, Division-free, and access conflict among the three types of Se should be captured, and other se cannot be recovered.
9. Run the setunhandledexceptionfilter function to run a program crash processor.
10. Using the exception handling mechanism in the case of few exceptions will not affect the performance, but may improve the performance.
11. when an exception is thrown: When a function is faulty and the function cannot continue to run without special measures, and these measures cannot be completed by itself, an exception should be thrown.
12. Timing of exception Capture:
When the function knows how to handle this exception
When this function knows how to handle this exception and the advanced function does not know how to handle it
When an exception is thrown, the process may crash.
When you need to sort out the allocated resources
13. The <stdexcept> in the C ++ standard library defines a standard class for exception reporting.
14. Use exceptions for errors that may only occur unexpectedly
15. MFC exceptions should be captured by pointers and released by the delete member functions, because they are usually allocated in the heap. Other C ++ exceptions should be captured by references, and manual release is not required, the exception captured by reference is passed in the stack and the polymorphism is maintained.
16. Exception specification (cannot be used together with the template ):
Function () -- can throw any exception
Function throw () -- cannot throw an exception
Function throw (cexception) -- only cexception-based exceptions can be thrown.
Note: exception specification is not recommended. It may cause program crash due to unexpected exceptions, and VC does not support
17. You can use the _ controlfp function to throw an exception to floating point numbers.
Debugging tools
Chapter 6 debugging in Windows
1. You can enter "@ Err" in the monitoring of the VC debugger to display the latest lasterror value, or use "@ err, HR" to display the text description corresponding to the error code. You can also use the formatmessage function to convert the error code to the text format.
2. Create a ing file for later debugging. Add the/MapInfo: exports compilation option when creating the file to output the export sequence number.
3. If the crash does not occur inside your code, you can get the address of your code returned through the stack dump information.
4. You can use the undname command line tool to parse the mixed function names in the ing file.
Chapter 7 use the VC ++ Debugger for debugging
1.
2. In the debugging version, inline is disabled by default.
3. Create debugging symbols for both the debug and release versions, and archive the PDB files.
4. Both the debug and release versions must be tested. It cannot be assumed that they are running the same.
5.
Debugging technology
Chapter 8 Basic Debugging Technology
1. Use the break function to debug the endless loop
2. Use @ CLK and d @ CLK = 0 in the invigilation window to observe the execution time of each step.
3. In the eax or eax + EDX register, view the return value of the function or the pointer to the returned data.
4. You can use the gdisetbatchlimit function to set or disable the batch processing of GDI for debugging the drawing code.
5. Use the getasynckeystate function to debug the wm_mousemove message.
6. Use spy ++ to debug messages
7. Any object returned by calling the fromhandle function cannot be saved across messages. It is only an object temporarily created by MFC and may be destroyed at any time.
Chapter 9 memory debugging
1. Memory leakage is often a sign of other program errors and bad programming habits
2. Always let new throw an exception in case of failure, instead of returning a null pointer that is easily ignored
3.
4. Using library functions provides more control capabilities and better portability. However, using MFC functions is slightly more convenient.
5. Define _ crtdbg_map_alloc to map all the heap functions in the program into its debugging version. In this way, you can obtain debugging information with the source file and row number.
Chapter 10 multi-threaded program debugging
1. Use the interlocked series locking functions to perform thread-safe operations on a single integer variable
2. when there is not much competition for locks, the efficiency of using the critical zone is higher than that of the lock. However, the critical zone is only used within the same process, and timeout parameters cannot be set, and the ownership of multiple critical zones cannot be applied for at the same time.
3. Using appropriate timeout parameters in the watiforsingleobject function can effectively avoid deadlocks
4. When mutex lock is used (not a critical section), using the waitformultipleobjects function is the most effective way to avoid deadlock.
5. The best way to handle timing-related problems is to trigger potential errors.
6. Use the volatile keyword to prevent variable access errors caused by Compiler Optimization in multithreaded programs
7. Create an "automatic lock" class and use its constructor and destructor to obtain and release the lock resources. In this way, the lock resources can be correctly released even when an exception occurs.
8. Try to use the top-level threads to create and clean up functions to avoid resource leaks and unprocessed exceptions. For example, when using the MFC framework for development, the afxbeginthread and afxendthread functions provided by MFC are used, instead of the _ beginthreadex and _ endthreadex functions of CRT, as well as the createthread and exitthread functions of windowsapi.
9. If you need to use MFC in the thread, this thread must be created by MFC
10. The correct method to close an MFC thread 1 (the cwinthread object will call the Destructor by itself ):
Method 2 (do not let cwinthread object self-analysis ):
11. Using the outputdebugstring function in multiple concurrent threads to output debugging information may serialize the thread execution.
12. When tracking a piece of code that can be called by multiple threads, you cannot assume that your current context is your environment. You can determine whether the context has been switched by observing the changes of local variables or calling the stack. You can also check the thread dialog box to determine the current thread.
13. the timeout time of the blocking function is measured by the actual time, instead of the valid CPU time. The time after the program is interrupted is also recorded as the timeout time, therefore, debugging often causes a time-out error that is unlikely to occur during normal operation.
14. Before debugging multi-threaded code, determine whether the problem is related to the version, debugger, system, and processor. From this information, you can know what to try first when using the debugger.
15. When an error occurs, check whether other threads are processing the same data as the error thread in the applicable thread dialog box.
16. using DW (@ TiB + 0x24) to view the threadid of the current thread can avoid frequent switching between the thread dialog box and the code window (not necessarily this value in WINXP, to be determined)
Chapter 2 com debugging
Chapter 1 unconventional strategies