introduction
The help information of the ASSERT error can often be seen on the C message bulletin board. Although this is usually a help request to eliminate Assert errors, almost all of the help people think that Assert itself is evil. I can fully understand the frustration of Assert errors to programmers. Your program is running, usually as you wish, suddenly a loud noise - an Assert error!
Then let's take a look at Assert, why they will appear there and what information we can get from them. I should emphasize that this article discusses how MFC handles Assert.
Linguistics Open Google Search, enter "Define Assert", and then click Search. "Assert" in WordNet has four meaning: 1. Ask, claim, claim ... (directly as a statement) 2. Confirm, verify, admit, oath ... (officially declared something realistic, such as: " Before God I Swear I am Innocent "-" I swear in front of God ") 3. Adhere to your own views of bold or strongly propose (yourself) to make you know. ("Women Should Assert Themselves More!") 4. Emphasize that it means that "The Letter Asserts A Free Society") is very close, but the fourth meaning is close to our Assert. Assert indicates that the conditions have been emphasized to be true. If the conditions are not true, the program will be in a serious failure, and you - programmers should receive this warning.
Assert In the code, when a programmer writes an Assert, it indicates that he is saying "This condition must be true, otherwise we will happen." For example, you are writing a function, I hope to get a string pointer. Void CMYCLASS :: MyFunc (LPCTSTR Szstringptr) {if (* szstringptr == '7') DOSMETHING ();} This function reads the memory segment pointed to by this pointer, so it is best to point to a legal and effective memory. Otherwise your program will crash! If you pass an empty pointer to this function, any program will have an error when calling this function. If the pointer is empty now, and your program crashes, you don't have enough information to handle it. Just only one message box, tell you a code address and you try to read the memory of the 0x0000000000 segment. The line of this code address to your actual code is not a relaxed thing, especially if you are dealing with this situation. Then let's make a small modification to this function. Void CMYCLASS :: MyFunc (lpctstr szstringptr) {assert (szstringptr);
IF (* szstringptr == '7') DOSMETHING ();} What to do here is to test SZStringPtr. If it is immediately crashing for air. collapse? Yes it is. But if you are using the debug compiler, it will collapse in a controlled manner. The MFC has some build-in plumbing to capture controlled crashes and connect them with a copy of the compiler. If you are running this program's debug, and askERT failed, you will see a message box similar to this.
This shows you which file that triggers Assert. You can choose Abort, abort the program; you can also choose Ignore to ignore this error, sometimes doing this; or you can choose Retry, try again. As long as your computer is installed on your computer, you will work even if you run this program alone. The difference between Release and Debug knows that Assert is important to compile assistants. If you compile your program with debug, the compiler will contain all the code in Assert (...). If you choose Release compilation, assert itself and all the code in parentheses disappear. It thinks you have tested the Debug version of your program and caught all possible errors. If you missed a mistake, and released a program with bugs, you can only pray that it can be safe. Sometimes it is also a good thing! Sometimes there will be this situation, you want to emphasize a certain condition in the debug version, and some you hope that in the debug version or in the Release version, you want you to emphasize the code. Live. It is necessary to use Verify at this time. In the Debug version, Verify can let you jump to the incident that is not satisfied in the compiler. In the Release version, the code in verify is still included in the executable. For example: Verify (MoveFile (SznewFileName); the above statement is in the Debug version, if the MoveFile () function fails, a debug assert is generated. No matter that the compiler, the MoveFile () function call will be Contains to the program. But in the Release version, the call failed will be simply ignored. Compared with the statement below: Assert (Movefile (SznewFileName); in the debug version, MoveFile () will be compiled and executed. And in the Release version, this line disappeared completely, and no files tried to be moved.
Tracking Assert in the MFC If you still continue to read down, I hope to learn about Assert errors, which is more likely that Assert you are debugging is not from your own code. If you are lucky enough, it will come from MFC because you have its source code. The first thing to remember is that it is unlikely that it is caused by bugs in the MFC. I don't deny that there is a bug in the MFC, but in my more than ten years I use MFC, I have never encountered an Assert is caused by the MFC's bug. The second thing to remember is that there must be a reason for Assert. You need to check the line of code that triggers an Assert error and figure out what it is testing. For example, a considerable part of the MFC class is around Windows control. In many cases, the package function transforms a SendMessage call looks like a general function to simplify your encoding. For example, the ctreectrl :: sortchildren () function accepts a tree handle and classifies its sub-items. In your code, you may be similar to the following statement: m_mytreectrl.sortchildren (hmyNode); in fact, this class sends a message to the tree control. You just call a function, while the MFC communicates the parameters that the message needs to be used. The following is a reformatted source code through the MFC function code: _AFXCMN_INLINE BOOL CTreeCtrl :: SortChildren (HTREEITEM hItem) {ASSERT (:: IsWindow (m_hWnd)); return (BOOL) :: SendMessage (m_hWnd, TVM_SORTCHILDREN, 0, (LPARAM) HITEM);} It is the first thing it is to show that the window handle in your CTREECTRL object is legal! Now I really don't know if you try to send a TVM_SortChildren message to a bad thing that does not exist. What I know is: I hope that I am trying to do it so much. If I am doing something that has no success, Assert is here to warn me directly. So if you encounter an Assert error while calling a function like that, you'd better look at the failed row and will find that it is emphasizing that the window handle must be an existing window. That is the only thing it emphasizes. If it fails, the only possibility is that the handle window does not exist. Those are the clues you track. The above is a concise example shows how the MFC uses Assert, and how you find MFC assert because of your project. Let us now take a look at how to apply Assert in his code. Void CMYCLASS :: MyFunc (LPCTSTR SZSTRINGPTR) Or come to see this function, I mentioned in front of using a simple check to make the passing pointer is not empty. In fact, we can do better than above. Both MFC and Windows itself provide a string function, we can use them to measure whether a pointer points to a valid memory. Void CMYCLASS :: MyFunc (szstringptr); assert (AFXSValidString (szstringptr)); if (* szstringptr == '7') DOSMETHING ();} The first statement is only captured, ie Empty pointer. Together with the second statement, we can test whether the pointer points to the effective memory. This test checks if you have permissions to read this segment, and the memory segment contains the end of the string. A related function is AFXISVALIDDRESS, which checks if you have the right to access the memory block in the previous call. You can also check if there is a read or write permission.
Other ASSERT Check that in addition to the two inspections mentioned, it is also possible to check if a passed object is a particular type. If you are writing a program that handles the CEMPLOYEE object and the CPRoduct object, it is clear that they cannot be interchangeable. Therefore, it is necessary to confirm that the function that handles the CEMPLOYEE object is only accepted only the corresponding type of object. In the MFC, you can do this below: void cmyclass :: AnotherFunc (CEMPLOEE * POBJ) {ask (pobj); // it can't be a null assert_kindof (CEMPLOYEE, POBJ);} As front, we first confirm This pointer is not empty. Then we check the type of this object pointer is a CEMPLOYEE type. Only for classes derived from COBJECT can be processed, and Runtime support is needed. Fortunately, adding Runtime support is really negligible. You must have declared that this object is at least Dynamic. Explain that in the MFC you can declare a class containing Runtime class information. You can do this by including the Declare_Dynamic (ClassName) macro in the class declaration, which contains IMPLEMENT_DYNAMIC (ClassName, BaseClassName) in the execution office. class CMyReallyTrivialClass: public CObject {DECLARE_DYNAMIC (CMyReallyTrivialClass) public: // Various class members and functions ...}; and the implementation fileIMPLEMENT_DYNAMIC (CMyReallyTrivialClass, CObject); ... // Other class functions ...
If you just want to use Assert_kindof macro, these two lines are enough. Now, when you write a program, you can use Assert_kindof macro anywhere to check if your object pointer you want. If not, your program will collapse in a controlled manner as mentioned earlier and receive an ASSERT given by the debugger. If your object already contains a Declare_DyncReate macro or a Declare_Serial macro, you don't need to use Declare_Dynamic because these macros have the runtime class information you need for the assert_kindof macro.
Conclusion The above explains how to capture the Runtime error with Assert and bring you to the debugger to cause the assert error. We have seen how to trace the cause of Assert failure. Along this idea, we learned how to test the validity of the pointer to the memory in our own code; how to check if the object pointer we get is required. In recent years, I have been using Assert as a runtime checker in my code, I have benefited a lot. I rarely encountered the problem that the program caused by an empty pointer or the type of object pointer is to crash.