|
From: an in-depth analysis of one of the most common causes of release errors in MFC I don't know if there are any similar articles on the Internet, so the younger brother is brave enough to make a ugly look here; Recently, many people post that their MFC program release version will go wrong, but the debug version will not go wrong. I remember that I encountered a similar problem two years ago, however, I did not conduct any in-depth research. I have made an in-depth discussion on this issue over the past two days and found a very easy mistake, this is also related to the VC Compiler (I don't know if it is a Microsoft Bug or what is going on). First, let's look at an example project: Create a dialog project with VC, add a new dialog window, and generate a dialog window class; create the non-modal dialog window of the new dialog window in the onok event of the main dialog window, for example: Void cadlg: onok () { M_pdlg = new cdlg1; // m_pdlg is a class member variable and a pointer to the new dialog window. M_pdlg-> Create (idd_dialog1 ); M_pdlg-> showwindow (sw_show ); } Then add a custom message: wm_mymsg; Send the wm_mymsg message to the main dialog window in the onok event of the new dialog window; Void cdlg1: onok () { Cwnd * pwnd = getparent (); Pwnd-> sendmessage (wm_mymsg ); } What I want to talk about below is the most critical. We usually have two methods to respond to wm_mymsg messages. One is to overload the windowproc virtual function in the main dialog window, then respond to the message within the function, for example: Lresult cadlg: windowproc (uint message, wparam, lparam) { Switch (Message) { Case wm_mymsg: { ...... Break; } } Return cdialog: windowproc (message, wparam, lparam ); } This method usually does not cause errors; Next we will look at the second method to respond to this message; First, add a function to the main dialog window, for example: Void cadlg: onmymsg () { } Add one to the Message ing table in the main dialog window: Begin_message_map (cadlg, cdialog) // {Afx_msg_map (cadlg) On_message (wm_mymsg, onmymsg) //} Afx_msg_map End_message_map () In this way, when our sub-dialog window sends the wm_mymsg message to the main dialog window, MFC will call our onmymsg function, so an error occurs. First, let's look at the definition of the on_message macro; # Define on_message (message, memberfxn )/ {Message, 0, 0, 0, afxsig_lwl ,/ (Afx_pmsg) (afx_pmsgw) (lresult (afx_msg_call cwnd: *) (wparam, lparam) & memberfxn} If you are familiar with macro definition, you can see that when you expand the macro, it actually uses two parameter pressure stacks (wparam and lparam) and then calls the function pointer; Our function onmymsg does not have a parameter definition. In other words, the function returns a non-flat stack. This is why the release version program operates illegally; Specifically, we write the above onmymsg function as follows: Void cadlg: onmymsg () { MessageBox ("test "); } Then let's look at its assembly code: Push 0 Push 0 Push 403020 H Call 004017ca RET We will not see it before. Let's look at the last sentence: RET Now, it's RET (of course, RET is the result of our function definition), rather RET 8 And so on (this is because our function does not define parameters, so we can directly RET ). In this way, the two parameters that we press the stack before the function do not perform the flat stack action. If the function returns, the operation will be invalid if the stack is not balanced; In other words, if our program is written as follows: Void cadlg: onmymsg () { MessageBox ("test "); _ Asm ret 8; } So the release version will not report an error (on the contrary, the debug version will report an error). If you do not believe it, please try it out, but it is wrong to write it like this. Please do not write it like this when writing a program, this is only evidence of the situation of the message ing function's horizontal stack; Why is there no problem with the debug version? Let's take a look at the compilation below: MoV ECx, dword ptr [ebp-0Ch] MoV dword ptr fs: [0], ECx Pop EDI Pop ESI Pop EBX Add ESP, 5ch Cmp ebp, ESP Call _ chkesp (004022fc) MoV ESP, EBP Pop EBP When VC compiles the debug program of MFC, it adds a code similar to the above Code after the function. The function of the code is to detect ESP and check whether the stack is flat, if not, the stack is forcibly flattened, so the debug version program won't make such a mistake. Why does Microsoft want to do so, please take a look at it together. (You are welcome to discuss it with me ); To sum up, when compiling the MFC program and ing our own message functions, we either use the first method, overload the windowproc virtual function, or use the second method, however, the function must define two parameters (wparam and lparam), even if they are useless. In this way, release errors can be avoided in most cases; In addition, I will mention this macro here: On_message_void This macro is defined in "afxpriv. H". This macro is opposite to on_message, and its message ing function cannot contain parameters. That is, if the macro is used for message ing, the message ing function cannot contain parameters. If the parameter is included, a release version error will occur, and the debug version will not be faulty; Finally, no matter which macro is used to reflect the message response function above, no matter what the message response function is defined as, VC will not report an error during compilation, therefore, this error will be hidden in depth and will not be found until you release the release version, and the program will be operated illegally; The above only represents my opinion. If you disagree, you are welcome to join the discussion; --------------------------------------------------------------- Http://expert.csdn.net/Expert/topic/2539/2539864.xml? Temp =. 9315149. --------------------------------------------------------------- Ha, vc7 will report an error. I really don't know. It seems that Microsoft has realized that this is a bug; --------------------------------------------------------------- This is a bug in MFC. Let's take a look at the msdn document: MS-help: // Ms. vscc.2003/ms. msdnqtr.2003feb. 2052/vccore/html/vcrefwhatsnewlibrariesvisualc70.htm # vcrefwhatsnewlibrariesmfcvisualc70 The following libraries in Visual C ++. NET may be added or changed. ....... Microsoft basic class (MFC) Library * The Reference topic for MFC contains hundreds of new code examples. * Static forced type conversion and MFC message ing start with Visual C ++. net. MFC performs more rigorous type checks on the return types and parameter types of message processing functions. These new behaviors mark potentially insecure message processing functions with error messages to notify developers of possible problems. MFC uses static forced type conversion for on_message, on_registered_message, on_thread_message, and on_registered_thread_message. For example, in the past, developers could use a member function that returns void instead of lresult for on_message or on_registered_message, without reporting any errors during compilation. With Visual C ++. net, you can capture potential errors and mark them as errors. Developers can fix this potential problem by replacing the return type (with lresult) and re-compiling. * DHTML Editing components: chtmleditctrl, chtmleditview, and chtmleditdoc. ......... The vc7 interface is not used, and the speed is slow. Otherwise, it is worth upgrading. --------------------------------------------------------------- By the way, we recommend that you use the release version to do things in the future, so that problems like the above will not occur. Some people It may be said how to debug with the release version. The following solution can be used. After debugging, change to the original settings before publishing Http://expert.csdn.net/Expert/TopicView1.asp? Id = 2555224 View my answers Release Version One-Step tracking method: (it may have been a piece of cake for everyone) Select Win32 release and Project-setting-C/C ++-category-General -Optimization-disable (Debug) -Debug info-program database -Link --- Generate debug info In addition, ask friends to hold these two posts. It took me a long time to reply to this post. Maybe for those Debug and release are not very helpful. Not my post, but the knowledge involved Very comprehensive. Http://expert.csdn.net/Expert/TopicView1.asp? Id = 2539864 Http://expert.csdn.net/Expert/topic/2553/2553540.xml? Temp =. 2079431. I care about technology. Hope to become friends with people with lofty ideals (caring for Technology) I agree with woaini5994 (lonely pig ). This is not an advertisement. Do not delete the moderator --------------------------------------------------------------- The first release mode bug encountered and solved "Using manually added parameters in the Response Function added by Class Wizard will cause the debug mode to run normally, but the release mode operation is invalid ." Cause of estimation: the default on_control message response function prototype of MFC is (void) PFN (void). Therefore, when the MFC function type declaration is not changed, calling with additional parameters will cause the function return address on the program stack to be incorrectly used as a function parameter in the release mode, and the return address of the function is naturally incorrect, resulting in access violation. Solution: 1. Change the afxsig_vv corresponding to the Message response function declaration to the afxsig_xx of the corresponding function type, and replace the afxsig_vv with the new statement (the original macro is expanded, and afxsig_vv with afxsig_xx) with the on_control macro. 2. Move the function body of the message response function to a custom general class function and use parameters in the class function. The message response function calls only class functions. (This method is only applicable when default parameters are added to the Message response function) Address: http://read.newbooks.com.cn/info/114380.html |