Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

"Use MFC in static/shared" crashes for static

Posted on 1998-08-04
12
Medium Priority
?
877 Views
Last Modified: 2013-11-19
Hi !

I have a VC++ 5.0 mainframe application, whose only job is to  launch somes DLLs:
it consists of a dialog box with only a menu, when selecting a menu item, it calls a DllInit() from one of the associated DLLs.
Those DLLs, created with VC++5.0, are dialog boxes with buttons, to do some testing, for example FTP operations.
They are compiled with "Use MFC in a static library" option.

If the mainframe is compiled with Mfc dynamically linked, everything's perfect:
when selecting "Debug FTP" on main menu, the dialog box with ftp operations shows up.

If the mainframe is compiled with Mfc statically linked,
when selecting "Debug FTP" on main menu, the application crashes. The crash point is into afxwin1.inl:

_AFXWIN_INLINE HINSTANCE AFXAPI AfxGetResourceHandle()
      { ASSERT(afxCurrentResourceHandle != NULL);
            return afxCurrentResourceHandle; }

When tracing into the DLL, the error occurs at OnInitDialog() into DLL Dlg class:
          m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

if removing that line, the same error occurs at       
      CDialog::Create(CFtpDebugDlg::IDD, this);


The Dlls are created like this:
init and export function:


CFtpDebugDlg* mp_FtpDebugDialog;

static AFX_EXTENSION_MODULE FtpDebugDLL = { NULL, NULL };

extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
      if (dwReason == DLL_PROCESS_ATTACH)
      {
            TRACE0("FtpDebug.DLL Initializing!\n");
            
            // Extension DLL one-time initialization
            AfxInitExtensionModule(FtpDebugDLL, hInstance);

            // Insert this DLL into the resource chain
            new CDynLinkLibrary(FtpDebugDLL);
      }
      else if (dwReason == DLL_PROCESS_DETACH)
      {
            TRACE0("FtpDebug.DLL Terminating!\n");
      }
      return 1;   // ok
}


extern "C" DLLEXPORT BOOL InitFtpDebug(void)
{
      HWND ForegndWnd =GetForegroundWindow();

      mp_FtpDebugDialog = NULL;
      mp_FtpDebugDialog = new CFtpDebugDlg();
      // call FtpDebug debug window creation
      mp_FtpDebugDialog->Create(ForegndWnd);
      mp_FtpDebugDialog->ShowWindow(SW_SHOWNORMAL);

      return TRUE;
}




///////////////////////////////////////////////////////////////
Dlg Class/////////////////////////////////////////////////
///////////////////////////////////////////////////////////////

CFtpDebugDlg::CFtpDebugDlg(CWnd* pParent /*=NULL*/)
      : CDialog(CFtpDebugDlg::IDD, pParent)
{
      //{{AFX_DATA_INIT(CFtpDebugDlg)
            // NOTE: the ClassWizard will add member initialization here
      //}}AFX_DATA_INIT
      // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
      m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

      //Added for DLL
      ASSERT(m_pFtpDebugParent != NULL);
      m_pFtpDebugParent = pParent;
      m_nFtpDebugID = CFtpDebugDlg::IDD;
}

//////////////////////////////////////////////
// Create:                                                      //
//            this function creates  window,      //
//            affects its identifier and parent,      //
//            initialises its top left corner's      //
//            position.                                          //
//////////////////////////////////////////////
void CFtpDebugDlg::Create(HWND hDcrWnd)
{
      CWnd pWndInsertAfter;

      // create / open debug window
      CDialog::Create(m_nFtpDebugID, this);
      pWndInsertAfter.FromHandle(hDcrWnd );
      SetWindowPos(  &pWndInsertAfter,  0,  0,  0,  0,  SWP_NOSIZE );

}

Thanks for you ideas,

Mike.
0
Comment
Question by:eskimo100997
12 Comments
 

Author Comment

by:eskimo100997
ID: 1320212
Edited text of question
0
 

Author Comment

by:eskimo100997
ID: 1320213
An Ice cream is offered to the first who finds the solution !
0
 

Expert Comment

by:TangCheng
ID: 1320214
 I already happed this question.I think this is a MFC's Bug.

  I already found the reason. Because if you use to dynamically linked to run your program, the DLL's Instance is same as application's Instance(App's hInstance is :0x40000, DLL's hInstance is:0x40000 too).So if DLL want to load Resource, it will search resource in application's resource address.So the application often crashes.

  If you use to static linked to run your program, the DLL's Initial Address is realy DLL's Address(0x100000).So you can run it good.
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 

Author Comment

by:eskimo100997
ID: 1320215
the DLL's Initial Address is realy DLL's Address(0x100000), and everything is staticaly linked, main and DLLs.
It does perfectly run when dynamicaly linked.
0
 

Author Comment

by:eskimo100997
ID: 1320216
Adjusted points to 300
0
 
LVL 8

Expert Comment

by:Answers2000
ID: 1320217
Your mistake is that the DLLs should be built to be MFC Extension DLLs (using shared MFCs) otherwise you have multiple independant copies of MFC in the same program fighting over common names & resources.

To change existing code, I'd recommend creating new empty DLLs with the class wizard, and then adding the existing source into the new DLLs (Add File To Project).  This won't take long and should be pretty easy.

Also I'd suggest you make the main app use MFC in shared library.  You can change this easily from the project settings.
0
 

Author Comment

by:eskimo100997
ID: 1320218
The aim of that project is to be run onto some PCs with no MFC nor VC++ installed.
It can't be compiled with dynamic links to MFCs.
0
 
LVL 11

Expert Comment

by:mikeblas
ID: 1320219
What does "Crashes" mean?  Do you mean you get an assertion failure?  At what line of which file?  In which version of MFC? Are you saying the assertion in AfxGetResourceHandle() is failing?  If so, can you provide a symbolic stack trace?

Or do you get an unhandled exception?  If so, what's the symbolic stack trace look like?

On which operating system are you running?

It's really important to ask complete questions if you want help.

B ekiM
0
 

Author Comment

by:eskimo100997
ID: 1320220
Sorry for the lack of information. I thought it was a common failure.
I'm working with VC++ 5.0, under win95

The error is "debug assertion failed" in Afxwin.inl line 22:
ASSERT(afxCurrentResourceHandle != NULL)

Call stack trace:

AfxGetResourceHandle() line 22
AfxFindResourceHandle(char * 0x000003a0, char * 0x0000000e) line 216 + 5 bytes
CWinApp::LoadIconA(unsigned int 0x000003a0) line 1022 + 26 bytes
CFtpDebugDlg::CFtpDebugDlg(CWnd * 0x00000000 {CWnd hWnd=0xc8000000}) line 28 + 17 bytes
InitFtpDebug() line 50 + 33 bytes
CWcp_ic_MainDlg::OnMenuFtp() line 168
DispatchCmdMsg(CCmdTarget * 0x0078fd04 {CWcp_ic_MainDlg hWnd=0x00000a84}, unsigned int 0x0000800d, int 0x00000000, void (void)* 0x00401028, void * 0x00000000, unsigned int 0x0000000c, AFX_CMDHANDLERINFO * 0x00000000) line 88
CCmdTarget::OnCmdMsg(unsigned int 0x0000800d, int 0x00000000, void * 0x00000000, AFX_CMDHANDLERINFO * 0x00000000) line 301 + 39 bytes
CDialog::OnCmdMsg(unsigned int 0x0000800d, int 0x00000000, void * 0x00000000, AFX_CMDHANDLERINFO * 0x00000000) line 96 + 24 bytes
CWnd::OnCommand(unsigned int 0x0000800d, long 0x00000000) line 2058
CWnd::OnWndMsg(unsigned int 0x00000111, unsigned int 0x0000800d, long 0x00000000, long * 0x0078fa70) line 1567 + 28 bytes
CWnd::WindowProc(unsigned int 0x00000111, unsigned int 0x0000800d, long 0x00000000) line 1555 + 30 bytes
AfxCallWndProc(CWnd * 0x0078fd04 {CWcp_ic_MainDlg hWnd=0x00000a84}, HWND__ * 0x00000a84, unsigned int 0x00000111, unsigned int 0x0000800d, long 0x00000000) line 217 + 26 bytes
AfxWndProc(HWND__ * 0x00000a84, unsigned int 0x00000111, unsigned int 0x0000800d, long 0x00000000) line 371
KERNEL32! bff73663()
KERNEL32! bff928e0()


Hope this will help.
0
 
LVL 1

Accepted Solution

by:
sudhirbrat earned 2400 total points
ID: 1320221
When you are loading a resource from a DLL, you should change the resource handle of your application to the DLL resource handle.

Try following line of code when ever your calling resource related functions like LoadIcon, etc...

AFX_MANAGE_STATE(AfxGetStaticModuleState());

Try this and let me know the result.
0
 

Author Comment

by:eskimo100997
ID: 1320222
Great !
0
 
LVL 1

Expert Comment

by:sudhirbrat
ID: 1320223
Where is my ICE CREAM !!!!!
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction: Displaying information on the statusbar.   Continuing from the third article about sudoku.   Open the project in visual studio. Status bar – let’s display the timestamp there.  We need to get the timestamp from the document s…
Introduction: Dialogs (2) modeless dialog and a worker thread.  Handling data shared between threads.  Recursive functions. Continuing from the tenth article about sudoku.   Last article we worked with a modal dialog to help maintain informat…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Are you ready to place your question in front of subject-matter experts for more timely responses? With the release of Priority Question, Premium Members, Team Accounts and Qualified Experts can now identify the emergent level of their issue, signal…

963 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question