[转] An error message in GDI + programming and its cause analysis

xiaoxiao2021-03-05  23

The company does not let the piracy, prepare each software either replace it into open source, or write, look at it, it is the simplest number of ACDSEE (some advanced features are all used), line, start from this. Demand Analysis: Basic image viewing features, image format conversion feature, basic graphical transformation function. Technical Feasibility Analysis: The GDI provided by MS has provided a comparison of professional graphics display, format conversion function, and is easy to use. .... ok, ready, start dry. However, in the process of programming, there is an error message makes me very unconfil. The program has the following statement: bmPhoto = new Bitmap (THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, PixelFormat24bppRGB); each DEBUG compile time always report the following error: error C2660: 'new': function does not take 3 parameters thought it was the beginning of construction Bitmap The problem of functions, but check it, Bitmap clearly has a constructor: Bitmap (in int width, in int hotht, in pixelformat format = pixelformat32bppargb); what is the problem? Discussion on the Internet, eventually locking the problem in such a macro in the MFC program: #ifdef _debug # define new debug_new # undef this_filestatic char this_file [] = __file __; # ENDIF These lines will never cause us to pay attention What is the problem with the code? Why make our code report to compile errors as described above? Let's take a look at the definition of debug_new (in Afx.h): # if defined (_Debug) &&! Defined (_AFX_NO_DEBUG_CRT) / / Memory tracking allocationvoid * AFX_CDECL operator new (size_t nSize, LPCSTR lpszFileName, int nLine); # define DEBUG_NEW new (THIS_FILE, __LINE __) # if _MSC_VER> = 1200void AFX_CDECL operator delete (void * p, LPCSTR lpszFileName, int nLine); # Endif sees here you might want, New is become Debug_new by Define, and the latter has become new (...) by define, which is not a loop? Non-also. Since AFX.H is included earlier than any other header file (stdafx.h contains AFXWIN.H, afxwin.h also contains AFX.h, and MFC requires us to contain stdafx.h before any valid code, of course, this is not necessary So the definition of debug_new is earlier than #define new debug_new behind, that is, this Define is only valid for the rear code, the code in the AFX.h that has been included in front is invalid. Only the topic is now, now returns to the topic. The MFC overloads Operator New, is to facilitate positioning memory leaks, and the overloaded Operator New will record the __file__ and __line__ information corresponding to each of the memory allocated.

Generally speaking, the standard Operator New declaration is as follows: void * __ cdecl operator new (size_t); ie it has only one parameter, only one Size information is received. Our code int * pi = new int; // the Same as int * pi = new int (); or int * pi = new int [1]; equivalent to int * tpi = (int *) Operator new sizeof (int)); // attention: this line can not pass compilation if you have define DEBUG_NEWint * pi = tpi; Similarly, before the definition DEBUG_NEW, at the beginning of the article being given this statement: Bitmap * bmPhoto = new Bitmap (THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT , PixelFormat24bppRGB); equivalent to Bitmap * tbmPhoto = (Bitmap *) operator new (sizeof (Bitmap)); tbmPhoto-> Bitmap (THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, PixelFormat24bppRGB); // initialize variableBitmap * bmPhoto = tbmPhoto; but now, since DEBUG_NEW Using the overloaded Operator New: Void * AFX_CDECL Operator New (size_t nsize, lpcstr lpszfilename, int nline); the above code equivalent: Bitmap * TBMPHOTO = (Bitmap *) Operator new (SizeOf (bitmap), __file__, __LINE __); tbmPhoto-> BitmapBitmap (THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, PixelFormat24bppRGB); // initialize variableBitmap * bmPhoto = tbmPhoto; gdiplus.h in retrospect operator new statement (in the GdiplusBase.h): class GdiplusBase {public: Void (void * in_pvoid) {dllexports :: gdipfree in_pVoid);} void * (operator new) (size_t in_size) {return DllExports :: GdipAlloc (in_size);} void (operator delete []) (void * in_pVoid) {DllExports :: GdipFree (in_pVoid);} void * ( Operator new []) (SIZE_T IN_SIZE) {RETURN DLLEXPORTS :: gdipalloc (in_size);}}; it overloads Operator New, and does not provide Operator New, which can accommodate 3 parameters, based on such a fact: Different names Domain (referring to the overall namespace between the global namespace, the parent class, the subclass, global and class, the next level of namespace covers the definition of the previous level unless the call is called Level definition.

Therefore, the overall redefined Operator New cannot be used for Bitmap classes. It is also for this reason, the compiler will report: Bitmap * TBMPhoto = (Bitmap *) Bitmap :: operator new (sizeof (bitmap), __file__, __line __); error C2660: 'new': function does not take Take 3 parameters know At this point, you have to fix this problem, just load a few Operator New more than Class GdiplusBase. Class GdiplusBase corrected as follows: #ifdef _DEBUGnamespace Gdiplus {namespace DllExports {#include }; #ifndef _GDIPLUSBASE_H #define _GDIPLUSBASE_H class GdiplusBase {public: void (operator delete) (void * in_pVoid) {DllExports :: GdipFree (in_pVoid);} void * (operator new) (size_t in_size) {return DllExports :: GdipAlloc (in_size);} void (operator delete []) (void * in_pVoid) {DllExports :: GdipFree (in_pVoid);} void * (operator new []) (size_t in_size) {return DllExports :: GdipAlloc (in_size);} void * (operator new) (size_t nSize, LPCSTR lpszFileName, int nLine) {return DllExports :: GdipAlloc (nSize);} void operator DELETE (void * p, lpcstr lpszfilename, int nline) {DLLEXPORTS :: GDIPFree p);}}; #ndif // #ifndef _gdiplusbase_h} #ENDIF // #ifDef _debugok, the problem has been resolved, in fact, this is just a problem with Operator New, but this problem is due to debug_new this is not eye-catching macro, It became a bit complicated. Finally, you should pay attention when you perform Operator New overload: 1.New operator is not overloaded, you can overload the Operator New. New operator first calls the Operator New, then call the constructor (if any). This behavior of New Operator is not overloaded, and it is only Operator New, which is the memory allocation.

2. Overloading Operator New is a must very careful thing, and when writing MFC programs or the system you write, you should pay attention to the overall Operator New, you should pay attention to all #include header files. Before all Define, avoid the impact of the redefinition of NEW. You can try to add #include , you will receive a lot of inexplicable error tips (Debug compile), this is because #define new DEBUG_NEW and Static Char this_file [] = __file__; cause. 3. Operator New / Delete is similar to a static function, you can access them directly through the class name.

4. Understand the basic concept of Operator New, you must understand the implementation of Placement New / Delete in the header file NEW, the implementation of the Placement New / Delete in the header file new: #ifndef __placement_new_inline # define __placement_new_inlineinline void * __ cdecl operator new (size_t, void * _p) {return (_P);} #iF _msc_ver> = 1200INline void __cdecl operator delete (void *, void *) {return;} # endif # ENDIF attached: (reposted) C A variety of new introductions 1.New T first new New, call class (if you overload) or the global Operator New allocation space, then call the constructor with the parameters of the column column, usage is New Typename ( Initial_args_list). If there is no parameters, parentheses can generally be omitted. For example INT * P = new int; int * p = new int (10); int * p = new foo ("Hello"); destroyed by calling Delete: Delete P 2. New T [] This new NEW is used to create a dynamic object array. He calls the Operator New [] of the object to allocate the memory (if not, call the operator new, search order is the same), then call the object's 31M default Constructor initialization each object usage: new type [num_of_objects];, for example, int * p = new int [10]; using operator delete31m [] 3.New () T and new () t [] This is a parameter when it is destroyed. NEW, this form of New will call Operator New (Size_t, Othertype) to allocate memory, here is compatible with the type of the parameters in New Braces, which is usually used in a particular address component object, called For the Placement New, the premise is that Operator New (size_t, void *) has been defined, and the usual compiler has provided an implementation, including the header file, this implementation is just simply returning the specified address of the parameter, so NEW () The operator creates an object on the address in parentheses. What is needed, the second The parameter is not a void *, which can identify the legal type, which is determined by the C overload mechanism to call the Operator new. Of course, we can provide your own operator new (size_, type) to determine the behavior of New, For example, CHAR DATA [1000] [SIZEOF (FOO)]; Inline Void * Operator New (size_t, int n) {Return Data [n];} You can use such interesting syntax to create objects: foo * p = new (6 Foo (); // Indeficit Standard Library also provides a NothRow implementation: void * operator new (std :: size_t, const st :: nothrow_t, const st :: nothrow_t &) throw () void * operator new [] (std :: size_t, const st :: nothrow_t &) throw (); you can do not throw an abnormally new (notHrow) INT (10) when the calling new fails.

转载请注明原文地址:https://www.9cbs.com/read-35101.html

New Post(0)