VC + + Common bug prevention and solving methods

Source: Internet
Author: User
Tags readable

The C + + language is the mainstream development language of desktop system, especially system software and large-scale application software. The C + + language is known for its flexibility and is more complex. Writing robust code with C + + is more challenging. C + + allows dynamic memory management while also causing more and more memory-related problems.

To be able to effectively avoid potentially dangerous code in development, you should follow the C + + related coding specifications and idioms:

1, a base class or a class with a virtual function should declare its destructor as a virtual function.

2, prevent a memory leak in the constructor, do not throw an exception in the destructor.

3, use the corresponding form of new and delete. That is: Use Delete to release the memory of the new application, delete[] release new[] request.

4, the pointer must be initialized before it is used, and pointers to dynamic memory should be immediately empty after being freed.

5, if a resource is allocated in a class constructor, you need to provide the copy constructor and assignment operator explicitly, and release the resource in the destructor.

About the idiomatic Raii in C + +.

Raii English Meaning: Resource acquisition is initialization, resource acquisition is initialized. This principle or technique is used for the management of resources. The core idea is to use objects to manage resources, get resources in the object's constructors, and release resources in their destructors. In order to ensure that the dynamic application of memory can be released even in the event of an exception, the ideal way is to use the local variables to manage dynamic memory ownership (ownership), is called smart pointer. The AUTO_PTR in STL is designed to solve the problem of resource ownership, but it lacks support for reference numbers and arrays and cannot be used in STL containers. The Boost Library provides smart pointers that are relatively mature and of high practical value. Where shared_ptr is thread-safe and can be used in STL containers.

Bug Fix and debug:

Finding a problem is a prerequisite for solving the problem. Compared to repairing memory defects, it is more time-consuming and laborious to find memory defects and pinpoint the code that causes the defect. Identifying memory defects early and accurately is critical to improving development efficiency.
First, using assertions to expose memory defects early
An assertion is a Boolean debug statement used to detect whether a condition's value is always true when the program is running. Assertions are often used to confirm the input and output of a function, to check whether the object's current state is legitimate, and so on.
Use assertions in the following scenarios to help identify errors related to memory illegal access:
(1) Verify that the pointer is readable/writable.
At the entrance of the function, it is often necessary to verify that the content area pointed to by the pointer is readable/writable.
Typically, an assert (p!= NULL) detection form is used. However, the value of the pointer is not NULL and does not mean that the pointer points to a legitimate read/write memory. The Win32 API provides functions isbadreadptr, isbadwriteptr, Isbadstringptr,

The isbadcodeptr is used to detect whether the memory area pointed to by the pointer is readable/writable.
The C run-time library provides functions such as _crtis Validpointer, _CrtIsValidHeapPointer, and so on, and the MFC library provides

AfxIsValidAddress, afxisvalidstring functions to accomplish similar functions.
(2) for MFC-based programs, the ASSERT_VALID macro determines whether a pointer to a CObject-derived class object is valid by calling the overloaded AssertValid function. The ASSERT_VALID macro invokes the AssertValid function of the afxisvalidaddress function and CObject derived class object (refer to MFC source code Afx.h, objcore.cpp).
Second, check memory leaks with C run time library
VC + + 's C Runtime Library (CRT) provides a wide range of features to help users detect memory leaks. The CRT provides functions such as _CrtMemCheckpoint, _crtdump Memoryleaks, _CrtSetDbgFlag, and so on to help debug memory leaks. For non-MFC projects, to enable effective memory leak reporting, the following settings are required:

(1) Add the following code to the head of StdAfx.h and turn on the compiler/yu option:
#define _crtdbg_map_alloc
#include <stdlib.h>
#include <crtdbg.h>
#define DEBUG_NEW NEW (_normal_block, This_file, __line__)

(2) Ensure that the header of each. cpp file contains the following:
#include "stdafx.h"
#ifdef _DEBUG
#define NEW Debug_new
#undef This_file
static char this_file[] = __file__;
#endif

(3) Turn on the switch that reports the memory leak at the beginning of the program:
_CrtSetDbgFlag (_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
For MFC engineering, MFC has done a bit of work, just to make sure that the header of each. cpp file contains the above point (2). In some cases, it is necessary to know what is in the memory block of memory leaks, but a standard memory dump is only a 16 binary form of the memory header. In order to get more useful information, we need to request memory in the user block type (_client_ block) and use _CrtSetDumpClient to build the dump function of user block memory. Specifically, for classes that are not inherited from CObject, you need:

(1) Specify a user block subtype for each class/struct (refer to crtdbg.h).

(2) When requesting memory, use the overloaded new form:

void* __cdecl operator New (

size_t nSize, int nType, LPCSTR lpszfilename, int nLine)

(Refer to MFC source code afxmem.cpp), where Ntype is the subtype of the user block.

(3) Create a user block memory dump function that specifically handles each type of subtype that needs to be dumped (including dbgint.h).

(4) Register the user block memory dump function with _CrtSetDumpClient

(Refer to MFC source code DUMPINIT.CPP).

For classes inherited from CObject, MFC has done the basic work in accordance with the above methods

(Refer to MFC source code Afxmem.cpp, dumpinit.cpp). To effectively dump objects inherited from CObject, you need to: (1) Overload virtual function dump for each class inherited from CObject. (2) Add code afxdump.setdepth (1) In the initialization section of the program to open the depth dump.
Third, the use of VC + + environment debugging and diagnostic functions, check and find common memory defects
Understanding common memory defect problems and the symptoms in VC + + environment can help us reduce the occurrence of problems and modify the problem in time.
From the wrong manifestation, stack-related errors fall into two main categories: Stack overflow and function return information being corrupted
(1) Stack Overflow (overflow)

There are two main scenarios for this type of error:

1) too large local variables. By default, Windows retains 1M stack space for each thread. In the menu

Project->properties->configuration Properties---Linker->system can be seen in

The Stack reserve size option allows you to adjust the size of the reserved stacking space.

2) The number of recursive call layers is too deep.

During debugging, the call Stack window can discover the pattern of recursive calls to functions.

(2) The function return information is broken this type of error mainly has two situations:
1) write operations on local variables are out of range (overflow). During debugging, the obvious sign that the function stack is broken is that the call stack cannot be displayed, and the error occurs where the called function is about to return.
2) If there is a mismatch in the function arguments between the calling function and the called function, or if the calling specification is inconsistent.
In order to check for such errors, the/GS,/RTCs switch should be turned on when the code is compiled

(Set under Menu project->properties->configuration properties-> c/c++->code generation).
Another type of error is a dynamic memory error. The typical scenario is as follows:
(1) Memory write out of bounds. In debug builds, if it is a write overflow, you will receive a "Damage:after block ..." Trace

Message, you will receive a "Damage:before block ..." Trace message if you write down the overflow.
(2) Remove the illegal pointer. In debug builds, when you delete an uninitialized pointer or a non-heap pointer, you receive

_CrtIsValidHeapPointer assertion error.
(3) Multiple releases. In debug builds, if you delete the same pointer more than once, you receive an _block_type_is_valid assertion error. To prevent such errors, you should leave the delete pointer to dynamic memory empty immediately after it is placed.

Four, using Windows structured exception handling mechanism to handle the memory crash of release version software
During the release phase of the program, you should minimize program errors, especially memory crashes. If it crashes, you should "gracefully" exit and try to collect the running information when the program crashes to help the program vendor follow-up debugging. [6] The structured exception handling (structured Exception Handling,seh) mechanism of Windows is required to capture information such as illegal access to the memory and the instruction address and register contents of the illegal access. MiniDumpWriteDump is an API function provided by Dbghelp.dll (refer to MSDN), which is used to dump some information about user-mode programs (such as stack cases, etc.) to a file (such as a. dmp file), which can be Microsoft's Debugger (VC + + or WinDbg) is used for post-mortem debugging. Using this function requires Dbghelp.h, Dbghelp.lib, and Dbghelp.dll (these files can be found in the Windows Platform SDK). To debug code based on the. dmp file afterwards, you need to generate a debug symbols (PDB) file for the release software (open compiler/debug option). After you get the. dmp file, open the. dmp file with VC + + and then debug Execution (press F5). In this way, the scene of the crash will reappear.

Summary of common error messages:

One, unresolved external symbol (indeterminate external "symbol")

This error message is generated if the connector cannot find the referenced function, variable, or label in the same library and destination file. In general, there are two reasons for an error: One is the referenced function, the variable does not exist, the spelling is incorrect, or the error is used, and a different version may be used next.

one. LNK2001
1 caused by a coding error. does not match the program code or module definition (. DEF) file can cause LNK2001. For example, if you declare a variable "var1" within a C + + source file and try to access the variable as a variable "VAR1" within another file, the error occurs.
2. If the inline function used is in the. CPP files defined inside the header file instead of the default
will cause LNK2001 errors.
3. LNK2001 is generated when the function is called when the parameter type used does not match the type of the function declaration.
4. Attempting to invoke a virtual function from a constructor or destructor of a base class will cause LNK2001.
5. Be aware of the common nature of functions and variables, only global variables, functions can be common. static functions and static variables have the same usage scope restrictions. Attempting to access any static variable that is not declared within the file from outside the file causes a compilation error or LNK2001. Variables declared within a function (local variables) can only be used within the scope of the function. The global constants of C + + have only static connection performance. This is different from C, which can also produce LNK2001 errors if you try to use global variables in multiple files in C + +. A workaround is to include the initialization code for the constant in the header file when needed, and in the. CPP file, and another method is to assign a constant to the variable when it is used.
two. LNK2001
1 caused by compilation and linked settings. If the/nod (/NODEFAULTLIB) option is used at compile time, the runtime and MFC libraries required by the program are written to the target file module by the compiler when connected, but these libraries are not linked to the project file unless they are explicitly included in the file. Using/nod in this case will cause error LNK2001.
2. If you do not set a program entry for wWinMainCRTStartup, you will get the LNK2001 error message "unresolved external on [email protected]" When using Unicode and MFC.
3. When compiling with the/MD option, since all runtimes are kept within the dynamic-link library, the

in the source file for "func"

References to "__imp__func" in the target file. If you attempt to connect using a static library LIBC.LIB or LIBCMT.LIB, LNK2001 will occur on the __imp__func, and/MD will occur if you do not compile with the MSVCxx.LIB option.
4. When compiling with the/ML option, LNK2001 occurs on _errno if the LIBCMT.LIB link is used.
5. When compiling a debug version of an application, it also generates LNK2001 if the connection is made with a release modal library, and the same problem arises when connecting to the release application using the debug version of the modal library.
6. Mixed use of different versions of libraries and compilers can also cause problems, because the new version of the library may contain previous versions of the

Symbols and descriptions.
7. The use of inline and non-inline compilation options in different modules can cause LNK2001. If you open a function inline (/ob1 or/OB2) when you create a C + + library, but you close the function inline (without the inline keyword) in the corresponding header file that describes the function, you get the error message. To avoid this problem, you should flag inline functions with the inline keyword in the corresponding header file.
8. Incorrect/subsystem or/entry settings can also cause LNK2001.

VC + + Common bug prevention and solving methods

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.