我在EXE里面set_new_handler(MyNewHandler),然后在DLL里面分配内存(CMap SetAt...)
它调用MFC的内部CPlex分配内存.因为内存不够失败,然后进入我的MyNewHandler函数.
MyNewHandler返回0,按照MSDN上的说法因该抛出异常.然而我在DLL里面捕捉CMemoryException没有效果.CException也不行.我跟踪一看,原来没有抛出任何异常.然后MFC使用空指针出错.
我想知道为什么MFC没有抛出异常,有人知道伐
谢谢

解决方案 »

  1.   

    vc\mfc\src\plex.cpp
    CPlex* PASCAL CPlex::Create(CPlex*& pHead, UINT nMax, UINT cbElement)
    {
    ASSERT(nMax > 0 && cbElement > 0);
    CPlex* p = (CPlex*) new BYTE[sizeof(CPlex) + nMax * cbElement];
    // may throw exception
    p->pNext = pHead;  这里使用空指针
    pHead = p;  // change head (adds in reverse order for simplicity)
    return p;
    }
      

  2.   

    异常应该自己手动抛出吧?你试试这样
    void __cdecl newhandler( )
    {
       throw bad_alloc( );
       return;
    }
    set_new_handler (newhandler);/*内存分配操作*/
      

  3.   


    VC6是不符合标准的,在new不到足够内存的时候并不抛出异常,而是返回指针为0,由此导致了有些假设分配错误时抛出异常的STL在VC6中使用会出现某些问题。不知道你的问题是不是由于这个。
      

  4.   

    很有可能
    但我自己写的类却可以进入CMEMORYEXCEPTION ,我没有重载OPERATOR NEW
      

  5.   

    catch(...)
    {
        DWORD dwNum = GetLastError();}
      

  6.   

    catch(...)是可以捕捉到异常.
    但我更想知道是不是因为MFC在内存分配上和标准的不一致,导致目前的情况.有没有办法可以解决.
    AFXSETNEWHANDLER我也试过了.好像也没有效果
      

  7.   

    Catch(...) 不可以捕获到所有的异常,比如你的访问非法,
    是系统的结构化异常,你要用SHE,还有编译选项, 看看Window调试 这本书。
      

  8.   

    建议你去看看 HJ的 STL源码剖析 好像是第二章如果分配内存失败时 你首先要有自己的处理过程 这就是set_new_handler的意义.
    如果你没有的话 系统就会老实的抛出异常.也就是说 你必须自己写这种分配内存不成功的handler程序.
    晚上回去我给你看看。
      

  9.   

    谢谢。
    程序起因是这样的,公司程序需要控制内存使用量,定为当前可用物理内存+可用页文件的80%。因为无法作到实时控制,所以我在程序开始的地方将进程地址空间都保留了,然后释放那80%的空间。按照我的想法,程序不会使用超量了。然后我设定了NEWHANDLER,在这个函数我判断是否需要返回继续分配还是抛出异常。然而大多数情况,程序内存使用量会超过我的设定值,一般会超过20M左右,然后进入NEWHANDLER,更有时候会内存用完,然后死机。
    所以我现在怀疑是不是当进程地址空间不够的情况下,进程动用了系统为他保留的另外2G空间做处理的。或者说异常需要使用额外内存来完成处理,如果是这样的话,CMEMORYEXCEPTION就无法处理了,本身就内存不够了。
      

  10.   

    你分配内存不成功后想 做什么呢 我看你有 set_new_handler(MyNewHandler)
    那么这个MyNewHandler就是当分配内存不成功后的处理函数,我觉得你有两种方法:
    1.在MyNewHandler中释放一些内存,好让你下次new的时候有更多内存可用 那么下次new就可能成功,不过这样你需要对以前分配的内存处理好,就是说,你必须采用某种数据结构来表示你前面所分配的内存,那么后面才能按照你所愿释放.
    2. set_new_handler(0) 这样就系统就认为你取消了内存分配不成功后的处理函数,则系统会自动抛出 bad_alloc异常》
      

  11.   

    我确实在MyNewHandler中释放了一些内存,然后继续尝试分配,如果我的POOL里面没有数据的话,就返回0,在VC里面就是抛出CMEMORYEXCEPTION。
    bad_alloc在VC里面是没有的
      

  12.   

    你犯了一个不是C/C++的问题:模块之间的内存分配并不是都使用的相同的内存池——也就是说,MFC使用他自己(DLL中)的分配函数和堆。而你的程序使用你自己(EXE)的分配函数和堆。MFC在VC2.0的时候就有了,这个时候C++98标准还没有出来,所以,MFC的默认做法是在内存分配失败的时候返回NULL而不是跑出异常。当VC6.0出来的时候,MFC为了兼容,不太可能把这样的内存分配方式更改了(可能有很多的代码依赖于测试返回值是否是NULL而不是去捕获异常),所以,你看到的MFC分配失败返回NULL是正常的。不是VC6.0这点上不支持C++标准。可能的解决办法有:使用多线程DLL方式连接。或使用静态链接MFC
      

  13.   

    是的 bad_alloc 应该是std::bad_alloc,
    也确像楼上言:
    New 有些版本是会返回 0的 如果分配不成功,有些不成功的话 就抛出异常.楼主 那你set_new_handler中的函数的处理 可能还不够好
    你试试 use namespace std;
    然后抛出std::bad_alloc
      

  14.   

    我现在就是采用在MyNewHandler中判断,如果需要则抛出CMemroyException异常。
    现在碰到另外一个一直很困惑的问题,就是象我上面说的,进程地址空间用完的情况,程序进入我MyNewHandler花费了比较长的时间,而且内存会超过限度。
      

  15.   

    是这样的,如果我的虚拟内存+物理内存(可用)为1G的话,我先将进程地址空间全部保留(一般是2G左右,另外2G是系统保留的),然后释放800M(1G*80%),我的程序按我的想法只能使用800M了。然而用完800M以后,程序的内存开销还在上升,有时候要过很长时间才能进入MyNewHandler,也有时候内存会达到1G封顶,不进入我的MyNewHandler。所以蛮困惑的。在超过800M以后,进入MyNewHandler之前,这些内存开销是谁在用。
      

  16.   

    可能是这样的 系统分配内存不成功后 会有一个循环 该循环就是做1。不停的继续分配内存 2。抛出异常 但是我觉得你已经set_new_handler了 当分配内存一失败 就会马上进入你的处理程序的 
    难道是在那个循环里面 不停的分配 继续分配??你可以跟踪一下 看看.我先上班了.