我的如下程序:
class A
{pubic:
   create();
...};
class B
{
public:
  A a;
...}
B::onopen()
{a.create();
...}
其中B是主窗口类。A是一个子窗口类。onopen()是在B中打开一个A子窗口的命令处理函数,执行以上函数,A能创出,但我在关闭A窗口,就出现崩溃现象!
对B做如下小改动,就能正确运行:
class B
{
public:
  A* pa;
...}
B::onopen()
{pa->create();
...}
请教哪位高手告诉我其中原因,谢谢!

解决方案 »

  1.   

    老大们,说说CObject obj与CObject* pobj的内存分配原理,他们分别是什么时候构造,什么时候析构,怎样析构啊!!!只要说的有道理就加分,不够再加!!!
    Waiting ,Waiting ,Waiting......
      

  2.   

    对于栈中的对象(你上面的CObject obj就是这种情况),超出其作用域时就析构了;
    而对于堆中的对象(CObject* pobj所指向的对象)则要显式地delete pobj才能析构。
    从你上面的描述来看,似乎是你的 A a对象出了问题。对象a是一个窗口,因而它的数据就含有一个窗口句柄(设为hWnd),初始化时hWnd=NULL,当你用a.creat()之后,就hWmd有了一个实际的值,而窗口关闭后,该值又要重新变为NULL。只有这样,析构对象a时才能正确。我不知道你的这个窗口是如何创建的,也不知道它是如何关闭的,所以无法帮你找出确切的原因。
    从你的叙述中,你第一次a对象会自动析构,而出现崩溃,很可能是窗口已经关闭但hWnd没有=NULL;而第二次pa所指向的对象更本就没有析构,当然也不会出现第一次的情况。
      

  3.   

    说的非常好,但问题还是存在,现附上相关源代码,请指教:
    class CImportWnd : public CFrameWnd
    {
    DECLARE_DYNCREATE(CImportWnd)
    public:
    CImportWnd(){}; 
    virtual ~CImportWnd(){};// Operations
    public:
    BOOL Create(const CRect& rect, CWnd* pParentWnd); 
    }BOOL CImportWnd::Create(const CRect& rect, CWnd* pParentWnd) 
    {
    if(rect.Width()<300||rect.Height()<300)
    {
    AfxMessageBox("主窗口太小");
    return FALSE;
    }
    //创建预览窗口的框架窗口
    int x=(rect.Width()-300)/2;
    int y=(rect.Height()-300)/2;
    CreateEx(WS_EX_TOPMOST,NULL,"图象预览窗口",
    WS_VISIBLE|WS_CAPTION|WS_CHILD|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_BORDER,
    CRect(x,y,x+300,y+300),pParentWnd,0,NULL);
    }class CMainFrame : public CMDIFrameWnd
    {
    DECLARE_DYNAMIC(CMainFrame)
    public:
    CMainFrame(){};// Implementation
    public:
    virtual ~CMainFrame(){};
    protected:  
    CImportWnd m_pwndImport;// Generated message map functions
    protected:
    //{{AFX_MSG(CMainFrame)
    afx_msg void OnImportView();
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
    };void CMainFrame::OnImportView() 
    {
    CRect rc;
    GetClientRect(&rc);
    int x=(rc.Width()-300)/2;
    int y=(rc.Height()-300)/2;

    m_pwndImport.Create(rc,this);
    ::SetWindowPos(m_pwndImport.GetSafeHwnd(),HWND_TOP,
    x,y,300,300,SWP_SHOWWINDOW);

    }以上代码由我程序中拷贝,我删除了无关语句,其中的CImportWnd相当于我上文说的A,CMainFrame相当于B,再请高手指点,问题解决立即加分!!拜托,拜托!!!
      

  4.   

    他显示的错误信息是:debug assertion fail.
    expression:_crtIsVlidHeapPointer(pUserData);
      

  5.   

    关闭窗口后m_pwndImport可能已经自动析构,因此下面的代码可能引起崩溃,你在这个语句商社一个断点,调试一下看看是不是这个原因。
    ::SetWindowPos(m_pwndImport.GetSafeHwnd(),HWND_TOP,
    x,y,300,300,SWP_SHOWWINDOW);
      

  6.   

    调试时它叫我输入dbgheap.c文件的路径,请问这路径在哪啊?
      

  7.   

    dbgheap.c位于microsoft visual studio/vc98/crt/src, 但好象不是这方面的问题。
      

  8.   

    我把::SetWindowPos(m_pwndImport.GetSafeHwnd(),HWND_TOP,
    x,y,300,300,SWP_SHOWWINDOW);
    删掉之后,那m_pwndImport就没办法关掉了,这是为什么啊?
      

  9.   

    问题到底出在哪啊!!!!!?????????我调了一下,好象不是SetWindowPos的问题,从仅有的出错信息看,是出在析构上;我见调试信息列如下:
    反汇编信息:出错在最后一条语句:
    102123B8 74 21                je          _free_dbg_lk+12Bh (102123db)
    102123BA 68 80 E0 24 10       push        offset string "_BLOCK_TYPE_IS_VALID(pHead->nBlo"... (1024e080)
    102123BF 6A 00                push        0
    102123C1 68 F9 03 00 00       push        3F9h
    102123C6 68 84 E1 24 10       push        offset string "dbgheap.c" (1024e184)
    102123CB 6A 02                push        2
    102123CD E8 5E 15 00 00       call        _CrtDbgReport (10213930)调用栈信息:出错在第一条语句:_free_dbg_lk(void * 0x00432f34, int 4) line 1017 + 69 bytes
    _free_dbg(void * 0x00432f34, int 4) line 970 + 13 bytes
    CObject::operator delete(void * 0x00432f34) line 46 + 12 bytes
    CImportWnd::`scalar deleting destructor'(unsigned int 1) + 56 bytes请哪位高手帮我分析一下,错误是怎样产生的,怎样解决?????多谢了!!!!!!!!!
      

  10.   

    你在创建CImportWnd时使用了CWnd::CreateEx函数,但其中的窗口类名lpClassName=NULL.
    下面是msdn对CreateEx的说明:
    BOOL CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, LPVOID lpParam = NULL);lpszClassName(请下面最后一句)Points to a null-terminated character string that names the Windows class (aWNDCLASS structure). The class name can be any name registered with the global AfxRegisterWndClass function or any of the predefined control-class names. It must not be NULL.
      

  11.   

    我试过了,问题好象不是出在CreateEx,从调试看是析构的问题,可我不知怎么解决!!!
      

  12.   

    终于把你的问题搞清楚了。
    你的CImportWnd从CFrameWnd派生,我查了一下CFrameWnd的源代码:
    CFrameWnd::PostNCDestroy
    {
       delete this;    //主动析构

    这就是说:
    (1)CFrameWnd(及其派生类)的对象必须用new在堆上创建
    (2)析构时不能直接delete,而应该调用CFrameWnd::PostNCDestroy函数(事实上,关闭窗口时,Windows发送WM_DESTROY消息,该消息的处理函数OnDestroy将调用PostNCDestroy函数主动析构,根本不用你管)。
      

  13.   

    哪位大虾能告诉我OO,我将程序传给他,帮我查查病因,Thanks!
      

  14.   

    谢谢你啊,zhukeke!给你先加满分,不够再上http://expert.csdn.net/Expert/topic/2442/2442746.xml?temp=.2300836,
    那里还有50分,我给你加!能把你QQ告诉我吗?