我写了个DLL,里面封装了一个对话框,Settings中设的是Use MFC in a Static Library,再用这个DLL时出现了这样的问题,就是程序退出时崩溃,在CWnd::~CWnd中,不知是什么缘故,设成Use MFC in a Shared DLL没有这样的问题。

解决方案 »

  1.   

    我是这样做的:
    1、在向导中点MFC AppWizard(dll),生成一个支持MFC的DLL。
    2、在DLL中添加一个对话框资源。
    3、给对话框对应一个类m_MyDlg。
    4、在CXXXApp中添加InitInstance(),并在其中加一句
    m_MyDlg.Create(IDD_DIALOG1);
    5、添加一个全局的函数
    int ShowDlg()
    {
    m_MyDlg.ShowWindow(SW_SHOW);
    return 0;
    }
    6、在.def文件中导出ShowDlg
    7、编译,连接,将生成的.dll和.lib考入我的测试程序目录中。
    8、我在测试程序中添加这样的代码: #pragma comment(lib, "Dlg") int ShowDlg(); void CTestDlg::OnButton1() 
    {
    ShowDlg();
    }
    ----------------------------
    现象:
    1、点击测试程序中的Button1可以弹出对话框。
    2、退出时红叉出现。定位进程序,堆栈是这样的:CMapPtrToPtr::GetValueAt(void * 0x0007085e) line 179 + 3 bytes
    CHandleMap::LookupPermanent(void * 0x0007085e) line 90 + 22 bytes
    CWnd::DestroyWindow() line 959 + 15 bytes
    CDialog::~CDialog() line 159
    CMyDlg::~CMyDlg() + 37 bytes
    $E276() + 34 bytes
    doexit(int 0x00000000, int 0x00000000, int 0x00000001) line 353
    _cexit() line 294 + 11 bytes
    _CRT_INIT(void * 0x10000000, unsigned long 0x00000000, void * 0x00000001) line 157
    _DllMainCRTStartup(void * 0x10000000, unsigned long 0x00000000, void * 0x00000001) line 252 + 17 bytes
    NTDLL! 77f83c48()
    NTDLL! 77f8c4d4()
    KERNEL32! 77e7b110()
    doexit(int 0x00000002, int 0x00000000, int 0x00000000) line 392
    exit(int 0x00000002) line 279 + 13 bytes
    WinMainCRTStartup() line 212
    KERNEL32! 77e67903()---------------------------------
    按照我所说的步骤,改过程可以重现,前提是 Use MFC in a Static Library 。谁知道个中理由,分不够可以再加。
      

  2.   

    可能你的DLL与你的DLL所需信赖的DLL之间有冲突。
      

  3.   

    说错了一个地方:
      3、给对话框对应一个类m_MyDlg。
    应该是:
      3、给对话框对应一个类CMyDlg。m_MyDlg 被我设成了全局的,我名字起得不好,属笔误。
      

  4.   

    你的dll是哪种类型的?
    Regular DLL中的哪种?
    是不是动态链接到MFC的规则DLL?
    还是Extension DLL~
      

  5.   

    如果 Use MFC in a Static Library 的话,我的Dll只用到Kernel32.dll等Windows的DLL,我觉得不会与这些DLL有冲突呀。
      

  6.   

    在ShowDlg函数开始处添加 AFX_MANAGE_STATE(AfxGetStaticModuleState());  试试?
      

  7.   

    to  rivershan(笨猫)(C++/VC初学者) :
    不是Extension DLL
      

  8.   

    你开始建立"MFC AppWizard(dll),生成一个支持MFC的DLL"时选得什么?
      

  9.   

    to rivershan(笨猫)(C++/VC初学者) :
    Regular DLL using Shared MFC DLL
      

  10.   

    to rivershan(笨猫)(C++/VC初学者) :
    我刚试过,用Regular DLL with MFC staticlly linked也不行
      

  11.   

    to shinespring(shine):
    试过了,不行呀!
      

  12.   

    int ShowDlg()
    {
                     AFX_MANAGE_STATE(AfxGetStaticModuleState());
                     CCMyDlg m_MyDlg;
                     m_MyDlg.DoModal();
            return 0;
    }去掉m_MyDlg这个全局变量,或者你用指针
      

  13.   

    请问aprilsnow?
    解决了没有呀?
    我也遇到相同的问题了
      

  14.   

    See the comment below, FYI :MFC DLLs—Extension vs. Regular
    We've been looking at Win32 DLLs that have a DllMain function and some exported functions. Now we'll move into the world of the MFC application framework, which adds its own support layer on top of the Win32 basics. AppWizard lets you build two kinds of DLLs with MFC library support: extension DLLs and regular DLLs. You must understand the differences between these two types before you decide which one is best for your needs. 
    Of course, Visual C++ lets you build a pure Win32 DLL without the MFC library, just as it lets you build a Windows program without the MFC library. This is an MFC-oriented book, however, so we'll ignore the Win32 option here.An extension DLL supports a C++ interface. In other words, the DLL can export whole classes and the client can construct objects of those classes or derive classes from them. An extension DLL dynamically links to the code in the DLL version of the MFC library. Therefore, an extension DLL requires that your client program be dynamically linked to the MFC library (the AppWizard default) and that both the client program and the extension DLL be synchronized to the same version of the MFC DLLs (mfc42.dll, mfc42d.dll, and so on). Extension DLLs are quite small; you can build a simple extension DLL with a size of 10 KB, which loads quickly. If you need a DLL that can be loaded by any Win32 programming environment (including Visual Basic version 6.0), you should use a regular DLL. A big restriction here is that the regular DLL can export only C-style functions. It can't export C++ classes, member functions, or overloaded functions because every C++ compiler has its own method of decorating names. You can, however, use C++ classes (and MFC library classes, in particular) inside your regular DLL. When you build an MFC regular DLL, you can choose to statically link or dynamically link to the MFC library. If you choose static linking, your DLL will include a copy of all the MFC library code it needs and will thus be self-contained. A typical Release-build statically linked regular DLL is about 144 KB in size. If you choose dynamic linking, the size drops to about 17 KB but you'll have to ensure that the proper MFC DLLs are present on the target machine. That's no problem if the client program is already dynamically linked to the same version of the MFC library. When you tell AppWizard what kind of DLL or EXE you want, compiler #define constants are set as shown in the following table.  Dynamically Linked to Shared MFC Library Statically Linked* to MFC Library 
    Regular DLL _AFXDLL, _USRDLL _USRDLL 
    Extension DLL
     _AFXEXT, _AFXDLL unsupported option 
    Client EXE _AFXDLL no constants defined 
    * Visual C++ Learning Edition does not support the static linking option. If you look inside the MFC source code and header files, you'll see a ton of #ifdef statements for these constants. This means that the library code is compiled quite differently depending on the kind of project you're producing. The Shared MFC DLLs and the Windows DLLs
    If you build a Windows Debug target with the shared MFC DLL option, your program is dynamically linked to one or more of these (ANSI) MFC DLLs: mfc42d.dll Core MFC classes 
    mfco42d.dll ActiveX (OLE) classes 
    mfcd42d.dll Database classes (ODBC and DAO) 
    mfcn42d.dll Winsock, WinInet classes 
    When you build a Release target, your program is dynamically linked to mfc42.dll only. Linkage to these MFC DLLs is implicit via import libraries. You might assume implicit linkage to the ActiveX and ODBC DLLs in Windows, in which case you would expect all these DLLs to be linked to your Release-build client when it loads, regardless of whether it uses ActiveX or ODBC features. However, this is not what happens. Through some creative thunking, MFC loads the ActiveX and ODBC DLLs explicitly (by calling LoadLibrary) when one of their functions is first called. Your client application thus loads only the DLLs it needs. MFC Extension DLLs—Exporting Classes
    If your extension DLL contains only exported C++ classes, you'll have an easy time building and using it. The steps for building the EX22A example show you how to tell AppWizard that you're building an extension DLL skeleton. That skeleton has only the DllMain function. You simply add your own C++ classes to the project. There's only one special thing you must do. You must add the macro AFX_EXT_CLASS to the class declaration, as shown here: 
    class AFX_EXT_CLASS CStudent : public CObject
    This modification goes into the H file that's part of the DLL project, and it also goes into the H file that client programs use. In other words, the H files are exactly the same for both client and DLL. The macro generates different code depending on the situation—it exports the class in the DLL and imports the class in the client. The MFC Extension DLL Resource Search Sequence
    If you build a dynamically linked MFC client application, many of the MFC library's standard resources (error message strings, print preview dialog templates, and so on) are stored in the MFC DLLs (mfc42.dll, mfco42.dll, and so on), but your application has its own resources too. When you call an MFC function such as CString::LoadString or CBitmap::LoadBitmap, the framework steps in and searches first the EXE file's resources and then the MFC DLL's resources. If your program includes an extension DLL and your EXE needs a resource, the search sequence is first the EXE file, then the extension DLL, and then the MFC DLLs. If you have a string resource ID, for example, that is unique among all resources, the MFC library will find it. If you have duplicate string IDs in your EXE file and your extension DLL file, the MFC library loads the string in the EXE file. If the extension DLL loads a resource, the sequence is first the extension DLL, then the MFC DLLs, and then the EXE. You can change the search sequence if you need to. Suppose you want your EXE code to search the extension DLL's resources first. Use code such as this: 
    HINSTANCE hInstResourceClient = AfxGetResourceHandle();
    // Use DLL's instance handle
    AfxSetResourceHandle(::GetModuleHandle("mydllname.dll"));
    CString strRes;
    strRes.LoadString(IDS_MYSTRING);
    // Restore client's instance handle
    AfxSetResourceHandle(hInstResourceClient);You can't use AfxGetInstanceHandle instead of ::GetModuleHandle. In an extension DLL, AfxGetInstanceHandle returns the EXE's instance handle, not the DLL's handle.