微軟VC各版本BUG: error C2660: 'new' : function does not take 3 parameters

微軟VC各版本BUG: error C2660: 'new' : function does not take 3 parameters
2008-05-18 15:56
 
 
今天在用GDI+寫程序時,有
HatchBrush * brushDotDiamond = new HatchBrush(HatchStyle25Percent,color);
用VC6 SP6或VS2005編譯錯誤爲error C2660: 'new' : function does not take 3 parameters
這是VC的一個BUG,微軟至今還沒有解除。
解決辦法如下:
法一:在該CPP文件開頭部分註釋掉#define new DEBUG_NEW
#ifdef _DEBUG
//#define new DEBUG_NEW
#undef THIS_FILE
static charTHIS_FILE[] = __FILE__;
#endif
建議法二:在GdiplusBase.h文件中class GdiplusBase中添加如下代碼
//////////////////////////////////////////////////////////////////////////
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);
}
//////////////////////////////////////////////////////////////////////////
下面是轉載文章,作者:billdavid
不讓用盜版,遂準備逐一將各軟件要麼換成開源的,要麼就自己寫,看了看,就數Acdsee最簡單了(有些高級功能根本用不着),行,從這個入手吧。
需求分析:基本的圖片查看功能,圖片格式轉換功能,基本的圖形變換功能。
技術可行性分析:MS提供的GDI
+已經提供了比較專業的圖形顯示、格式轉換功能,而且簡單易用。
....

OK,就緒,開始幹吧。

但是在程序編寫的過程中,有條錯誤信息讓我很不解。程序中有如下語句:
bmPhoto
= new Bitmap( THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, PixelFormat24bppRGB );
每次DEBUG編譯的時候總是報告如下的錯誤:
error C2660
: 'new' : function does not take 3 parameters
開始以爲是Bitmap的構造函數的問題,但是查了一下,Bitmap明明有個構造函數:
Bitmap
(IN INT width,
        IN INT height,
        IN PixelFormat format = PixelFormat32bppARGB);
那會是什麼問題呢?上網討論了一下,最終將問題鎖定在MFC程序中的這樣一個宏定義上:
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
這幾行從來都不會引起我們注意的代碼有什麼問題呢?爲什麼會使得我們的代碼報告如上所述的編譯錯誤呢?
讓我們來看看DEBUG_NEW的定義(在afx.h中):
#if defined(_DEBUG) && !defined(_AFX_NO_DEBUG_CRT)

// Memory tracking allocation
void* AFX_CDECL operator new(size_t nSize, LPCSTR lpszFileName, int nLine);
#define DEBUG_NEW new(THIS_FILE, __LINE__)
#if _MSC_VER >= 1200
void AFX_CDECL operator delete(void* p, LPCSTR lpszFileName, int nLine);
#endif
看到這裏你可能會想,new被define成了DEBUG_NEW,而後者又被define成了new(...),這不是成了個循環?非也。由於afx.h早於任何其它頭文件被包含(stdafx.h包含afxwin.h,afxwin.h又包含了afx.h,而MFC要求我們在任何有效代碼之前包含stdafx.h,當然,這不是必須的),所以DEBUG_NEW的定義早於後面的#define new DEBUG_NEW,也就是說這個define只對後面的代碼有效,對前面已經include了的afx.h中的代碼是無效的。

上面只是題外話,現在回到正題。
MFC重載
operator new,是爲了方便定位內存泄漏,重載後的operator new會記錄下所分配的每塊內存對應的__FILE__和__LINE__信息。一般來講,標準的operator new的聲明如下:
void *__cdecl operator new(size_t);
即它只有一個參數,只接收一個size信息。我們的如下代碼
int* pi = new int; // the same as int* pi = new int(); or int* pi = new int[1];
等價於
int* tpi = (int*)operator new(sizeof(int)); // attention: this line cannot pass compilation if you have define DEBUG_NEW
int* pi = tpi;
同理,定義DEBUG_NEW前,文章開頭報錯的這條語句:
Bitmap
* bmPhoto = new Bitmap( THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, PixelFormat24bppRGB );
等價於
Bitmap
* tbmPhoto = (Bitmap*)operator new(sizeof(Bitmap));
tbmPhoto->Bitmap( THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, PixelFormat24bppRGB ); // initialize variable
Bitmap* bmPhoto = tbmPhoto;
但是現在,由於DEBUG_NEW使用的是被重載的operator new
void* AFX_CDECL operator new(size_t nSize, LPCSTR lpszFileName, int nLine);
上述代碼等價於:
Bitmap
* tbmPhoto = (Bitmap*)operator new(sizeof(Bitmap), __FILE__, __LINE__);
tbmPhoto->BitmapBitmap( THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, PixelFormat24bppRGB ); // initialize variable
Bitmap* bmPhoto = tbmPhoto;
回過頭來看gdiplus.h中的operator new的聲明(在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);
     }
};

它重載了operator new,並且沒有提供一個可以容納3個參數的operator new,同時基於這樣一個事實:
不同命名域(指全局命名空間與有名命名空間之間,父類與子類,全局與類內部)內進行重載時,下一級的命名空間會覆蓋掉上一級的定義,除非顯示調用上一級的定義。
因此,全局的重新定義的
operator new並不能用於Bitmap類。也正因爲這一原因,編譯器會報告:
Bitmap
* tbmPhoto = (Bitmap*)Bitmap::operator new(sizeof(Bitmap), __FILE__, __LINE__);
error C2660: 'new' : function does not take 3 parameters
知道了這一點,要修正這一問題,只需給
class GdiplusBase多重載幾個operator new即可。修正後的class GdiplusBase如下:
#ifdef _DEBUG

namespace
Gdiplus
{

     namespace
DllExports
     {

         #include <GdiplusMem.h>
     };

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章