none
Deserialization stops working if I load MFC DLL from regular DLL

    Question

  • Deserialization stops working if I load MFC DLL from regular DLL

    I have been asking this question before, but at that time I think it was to complex so I did not get any answer solving the problem for me.

    See http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/451add54-2813-4626-aa28-a7753605f69a

    Now I have made a test application showing the same problem.
    You can find the zipped code files at https://skydrive.live.com/?#cid=0977B1167FE01BB3&id=977B1167FE01BB3%21105&sc=documents.

    If I load a MFC extension DLL from a regular DLL then deserialization stop working if I call the MFC Extension DLL directly from the application.

    When I try to deserialize I get the following CArchiveException "an unnamed file contained an unexpected object."

    In addition the output in Visual Studio 2008 gives the following information when I run the debug version of SerializeTest:

    “Warning: Cannot load CSerializableClass from archive. Class not defined. CArchive exception: badClass. First-chance exception at 0x7c812afb in SerializeTestD.exe: Microsoft C++ exception: CArchiveException at memory location 0x0012edf8.”

    The following test code is run in CMFCDLL::DoIt

    void CMFCDLL::DoIt(void)
    {
    
    	BYTE * pBuf = (BYTE *)new char [1024];
    	{
    		CSerializableClass *pSerializableClass = new CSerializableClass;
    
    		CMemFile mf;
    		mf.Attach(pBuf, 1024);
    
    		CArchive ar(&mf, CArchive::store);
    		ar << pSerializableClass;
    		ar.Close();
    		mf.Detach();
    
    		delete pSerializableClass;
    	}
    	{
    		CSerializableClass *pSerializableClass = NULL;
    
    		CMemFile mf;
    		mf.Attach(pBuf, 1024);
    		CArchive ar(&mf, CArchive::load);
    		try
    		{
    			ar >> pSerializableClass;
    			ar.Close();
    			mf.Detach();
    
    			ASSERT(pSerializableClass && pSerializableClass->GetText() == _T("This is a serialize test"));
    
    			delete pSerializableClass;
    		}
    		catch(CArchiveException *p)
    		{
    			char str[500];
    			p->GetErrorMessage(str,500);
    			AfxMessageBox(str);
    			p->Delete();
    
    			ar.Abort();
    			mf.Detach();
    		}
    	}
    	delete pBuf;
    }
    
    

    The code that fails is "ar >> pSerializableClass". Any ideas why I get this problem?

    Why do I have to use a regular DLL?
    I am writing a .NET wrapper and the mixed mode DLL is a regular DLL accessing serialization in a MFC Extension DLL.

     

     


    Senior Software Engineer R&D
    • Edited by Kjell Arne Tuesday, January 24, 2012 12:00 PM Added link to test application at SkyDrive
    Tuesday, January 24, 2012 10:49 AM

Answers

  • Seems to work if you comment this line from InitMFCDLLFromRegularDLL:

     

        delete gpDynLinkLibrary;

     

     

    • Marked as answer by Kjell Arne Wednesday, January 25, 2012 11:46 AM
    Tuesday, January 24, 2012 8:39 PM

All replies

  • Now I have made a test application showing the same problem. I don't know how to attach code files so please mail me to get the zipped project. 86 KB.

     

    Publish the sources of test application on SkyDrive or other storage and give us the link, so we can investigate the issue.

     

     

    Tuesday, January 24, 2012 11:49 AM
  • Now I have made a test application showing the same problem. I don't know how to attach code files so please mail me to get the zipped project. 86 KB.

     

    Publish the sources of test application on SkyDrive or other storage and give us the link, so we can investigate the issue.

     

     


    Thank you.  https://skydrive.live.com/?#cid=0977B1167FE01BB3&id=977B1167FE01BB3%21105&sc=documents.
    Senior Software Engineer R&D
    Tuesday, January 24, 2012 12:01 PM
  • It cannot be that CSerializeClass is not available, or the new would fail.

    I notice that pSerializableClass is NULL, so your operator >>() must have to construct the relevant instance and populate it; presumably this is where it's failing. 

    Can you show us more of CArchive's declaration, its relevant constructor and the operator >>() ? [Already done, I see.]


    Answering policy: see profile.
    Tuesday, January 24, 2012 12:03 PM
  • It cannot be that CSerializeClass is not available, or the new would fail.

    I notice that pSerializableClass is NULL, so I your operator >>() must have to construct the relevant instance and populate it; presumably this is where it's failing. 

    Can you show us more of CArchive's declaration, its relevant constructor and the operator >>() ?


    Answering policy: see profile.


    I think the problem is related to CWinApp.   Both the application is derived from CWinApp and the regular dll is derived from CWinApp.

    Have a look at the full code at https://skydrive.live.com/?#cid=0977B1167FE01BB3&id=977B1167FE01BB3%21105&sc=documents

     


    Senior Software Engineer R&D
    Tuesday, January 24, 2012 12:06 PM
  • Hmm, did you notice the TODO: comment near the start of GeneralDLLApp.cpp relating to AFX_MANAGE_STATE(AfxGetStaticModuleState()); ?

    I suspect it's relevant.


    Answering policy: see profile.
    Tuesday, January 24, 2012 2:49 PM
  • Hmm, did you notice the TODO: comment near the start of GeneralDLLApp.cpp relating to AFX_MANAGE_STATE(AfxGetStaticModuleState()); ?

    I suspect it's relevant.


    Answering policy: see profile.


    Yes it is relevant.  That is way I am using it in

    void CGeneralDLL::DoIt(void)
    {
    	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    
    	m_pMFCDLL->DoIt();
    }
    

    It does not seem to have any effect in InitInstance() and ExitInstance().


    Senior Software Engineer R&D
    Tuesday, January 24, 2012 2:54 PM
  • I know, but you aren't using it in CMFCDLL::DoIt().
    Answering policy: see profile.
    Tuesday, January 24, 2012 2:57 PM
  • Seems to work if you comment this line from InitMFCDLLFromRegularDLL:

     

        delete gpDynLinkLibrary;

     

     

    • Marked as answer by Kjell Arne Wednesday, January 25, 2012 11:46 AM
    Tuesday, January 24, 2012 8:39 PM
  • I know, but you aren't using it in CMFCDLL::DoIt().
    Answering policy: see profile.


    MFCDLL is not a CWinApp DLL. 

    AFX_MANAGE_STATE(AfxGetStaticModuleState()) apply for regular DLLs accessing MFC extension DLLs.


    Senior Software Engineer R&D
    Wednesday, January 25, 2012 7:14 AM
  • Seems to work if you comment this line from InitMFCDLLFromRegularDLL:

     

        delete gpDynLinkLibrary;

     

     


    You are right!  The "main" application behaves differently.  I have to investigate and see why.

    The "main" application is a complex application which loads a lot of dlls for different purposes. 


    Senior Software Engineer R&D
    • Edited by Kjell Arne Wednesday, January 25, 2012 9:53 AM
    Wednesday, January 25, 2012 9:53 AM
  • Seems to work if you comment this line from InitMFCDLLFromRegularDLL:

     

        delete gpDynLinkLibrary;

     

     


    You are right!  The "main" application behaves differently.  I have to investigate and see why.

    The "main" application is a complex application which loads a lot of dlls for different purposes. 


    Senior Software Engineer R&D


    Your observation regarding deleting the "gpDynLinkLibrary" was the problem.  The DLL was removed from the MFC resource chain and added to the regular DLL resource chain.  The MFC DLL must exist in both.

    This problem applied for several DLLs with serialization that was dependent of each other.

    Thank you!  Problem solved :-)

     


    Senior Software Engineer R&D
    Wednesday, January 25, 2012 11:46 AM