none
DEBUG_NEW疑问? RRS feed

  • 问题

  • 在VC2008中:

    #include <fstream>
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #endif

    ----编译链接成功

    #ifdef _DEBUG
    #define new DEBUG_NEW
    #endif
    #include <fstream>

    ----报错
    d:\program files\microsoft visual studio 9.0\vc\include\xdebug(32) : error C2365: “operator new”: redefinition.....


    请问这是怎么回事?不是重载了NEW吗,怎么放在后面就是重复定义了,而放在前面就不是重复定义?请大虾们帮帮忙?
    我的疑惑是放前和放后的区别?

    --PRETHANKS

    2010年1月21日 1:01

答案

  • 首先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__)
    


    而afx.h是通过stdafx.h包含进来的。如果你创建的MFC工程默认包含stdafx.h。那么在各个编译单元的第一行都会默认添加include "stdafx.h"
    再看include <fstream>
    它会包含include <xdebug>文件
    在这个文件的第32行会第一次出现保留字new

     

    _MRTIMP2 __bcount(_Size) void * __cdecl operator new(size_t _Size,
    
    const std::_DebugHeapTag_t&, __in_z_opt char *, int)
    
    _THROW_BAD_ALLOC; // allocate from the debug CRT heap
    

    那么我们来整理一下影响编译的代码,你上面贴出的编译成功的代码变为
    #include "stdafx.h"
    #include <fstream> 
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #endif

    其实就是

     

    #define DEBUG_NEW new(THIS_FILE, __LINE__)
    
    _MRTIMP2 __bcount(_Size) void * __cdecl operator new(size_t _Size,
    
    const std::_DebugHeapTag_t&, __in_z_opt char *, int)
    
    _THROW_BAD_ALLOC; // allocate from the debug CRT heap
    
    #define new DEBUG_NEW
    


    此时,operator的声明是没有问题的。
    但是看看编译不过的那个情况

    #define DEBUG_NEW new(THIS_FILE, __LINE__)
    #define new DEBUG_NEW
    
    _MRTIMP2 __bcount(_Size) void * __cdecl operator new(size_t _Size,
    
    const std::_DebugHeapTag_t&, __in_z_opt char *, int)
    
    _THROW_BAD_ALLOC; // allocate from the debug CRT heap
    


    显然在operator new声明之前new 已经被预编译替换成new(THIS_FILE, __LINE__)
    那么operator new的声明变为了void* AFX_CDECL operator new(size_t nSize, LPCSTR lpszFileName, int nLine);的声明。
    且参数是错误的。所以编译是不通过的。


    麻烦把正确答案设为解答。
    2010年1月21日 2:43
    版主

全部回复

  • 首先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__)
    


    而afx.h是通过stdafx.h包含进来的。如果你创建的MFC工程默认包含stdafx.h。那么在各个编译单元的第一行都会默认添加include "stdafx.h"
    再看include <fstream>
    它会包含include <xdebug>文件
    在这个文件的第32行会第一次出现保留字new

     

    _MRTIMP2 __bcount(_Size) void * __cdecl operator new(size_t _Size,
    
    const std::_DebugHeapTag_t&, __in_z_opt char *, int)
    
    _THROW_BAD_ALLOC; // allocate from the debug CRT heap
    

    那么我们来整理一下影响编译的代码,你上面贴出的编译成功的代码变为
    #include "stdafx.h"
    #include <fstream> 
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #endif

    其实就是

     

    #define DEBUG_NEW new(THIS_FILE, __LINE__)
    
    _MRTIMP2 __bcount(_Size) void * __cdecl operator new(size_t _Size,
    
    const std::_DebugHeapTag_t&, __in_z_opt char *, int)
    
    _THROW_BAD_ALLOC; // allocate from the debug CRT heap
    
    #define new DEBUG_NEW
    


    此时,operator的声明是没有问题的。
    但是看看编译不过的那个情况

    #define DEBUG_NEW new(THIS_FILE, __LINE__)
    #define new DEBUG_NEW
    
    _MRTIMP2 __bcount(_Size) void * __cdecl operator new(size_t _Size,
    
    const std::_DebugHeapTag_t&, __in_z_opt char *, int)
    
    _THROW_BAD_ALLOC; // allocate from the debug CRT heap
    


    显然在operator new声明之前new 已经被预编译替换成new(THIS_FILE, __LINE__)
    那么operator new的声明变为了void* AFX_CDECL operator new(size_t nSize, LPCSTR lpszFileName, int nLine);的声明。
    且参数是错误的。所以编译是不通过的。


    麻烦把正确答案设为解答。
    2010年1月21日 2:43
    版主
  • 谢谢你的回答,我自己也研究了下,补充:
    。。。。。。
    那么operator new的声明变为了_Ret_bytecap_(_Size) _MRTIMP2 void * __cdecl operator new(THIS_FILE, __LINE__)(size_t _Size,
     const std::_DebugHeapTag_t&, _In_opt_z_ char *, int)
      _THROW_BAD_ALLOC; // allocate from the debug CRT heap

    我们可以把它化繁为简等价看成:

    int test(4, 5)(int a, int b);

    编译器在解析时,先解析到
    int test(4, 5)

    编译器认为它是在定义一种数据类型,就像我们平时:int test(4);
    而之前已经有了test的定义,而且之前把test定义为函数,于是编译器报错如下:
    error C2365: “operator new”: 重定义;以前的定义是“函数”

    之后又看到是int test(4, 5), 而不是int test(4);所以编译器又报错如下:
    error C2078: 初始值设定项太多

    2010年1月21日 7:27