Link to home
Start Free TrialLog in
Avatar of tullhead
tullheadFlag for United States of America

asked on

Assertion in appcore.cpp - why?

My MFC App dies right away when started, due to ASSERT in the CWinApp constrcutor.  It dies in the last line of this snippet:

CWinApp::CWinApp(LPCTSTR lpszAppName)
{
      if (lpszAppName != NULL)
            m_pszAppName = _tcsdup(lpszAppName);
      else
            m_pszAppName = NULL;

      // initialize CWinThread state
      AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();
      ENSURE(pModuleState);
      AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread;
      ENSURE(pThreadState);
      ASSERT(AfxGetThread() == NULL);

Now, my exe contains a built in static lib, and that static lib has in it a definition of a CWinApp subclass.  My confusion may also be conflated with the fact that I just made the leap from IDE 6.0 up to VS 2010 and I may be doing something wrong with linking in the static library.    Can someone point me where to look or give a hint as to what is likely wrong?  Thanks.
Avatar of pepr
pepr

Apparently, you expect the AfxGetThread() returns NULL. However, there is the following note in the official documentation (http://msdn.microsoft.com/en-us/library/0aa1ya36%28v=vs.100%29.aspx):
If you are porting an MFC project calling AfxGetThread from Visual C++ versions 4.2, 5.0, or 6.0, AfxGetThread calls AfxGetApp if no thread is found. In Visual C+ .NET and later, AfxGetThread returns NULL if no thread was found. If you want the application thread, you must call AfxGetApp.

You should probably check your expectations with the new version of Visual Studio, and fix the assert.
Avatar of tullhead

ASKER

This ASSERT is in appcore.cpp which is part of MFC (I suppose).  So, I can't (or shouldn't) go and change an assert inside part of MFC, right?   So, what should I really do to get around this issue?
Stupid question - does a Release Build work as expected?
Firstly, I am ATL oriented, and I did not use MFC. However, when new version of Visual Studio is used, it upgrades the solution file and namely the projects. To make the majority of older projects working the same way the older compiler did, it may use the older libraries, and sources.

Can you check whether the appcore.cpp is the part of MFC that comes with the new Visual Studio 2010?
jkr -- also dies immediately when built in Release mode.
do you have an application class derived from CWinApp? and did you create an instance of that class in one of your cpp files?

and that static lib has in it a definition of a CWinApp subclass

the instance of the application class may not be defined in the static library. it needs to be in the cpp file for your application class which must be a file of the mfc app project.

// myapp.cpp
#include "stdafx.h"
#include "myproject.h"
....
// the one and only application instance
MyApp theApp;

...
MyApp::MyApp()
{
    ....
}

Open in new window


Sara
Sara --

Yes, I have all that.
SOLUTION
Avatar of pepr
pepr

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
fyi:

the AfxGetThread() must return NULL in the CWinApp constructor cause the current thread for the instance was not yet completely created. if it doesn't return NULL there already was an application instance.

in case of a regular mfc dll, the dll has contrary to an extension dll (and of course also contrary to a static library) an own instance of the application object (which works as a proxy to the original object) but cause the dll is a separate executable the AfxGetThread nevertheless would return NULL in that case.

Sara
OK - I put a breakpoint on CwinApp::CWinApp and it hits it once when the main exe starts, then hits it a second time for the static DLL, and then dies in that call.  So.... I guess I've used dynamic DLLs in the past, and they have always had a CWinApp subclass object.  But, for this statically linked DLL, I cannot have one?
I modified my "static DLL" and made the "theApp" class there not a subclass oc CWinApp, and I had to comment out the message map stuff.   Nowwhen linked with my exe it all seems to work.   Have I done the right thing?    Seems kinda messy -- is this the "standard way" to convert a dynamic DLL to a statically-linked one?
actually there is no statically linked dll. dll means dynamic link library and static is contrary to dynamic.

a static library in vc++ means only that you put a bunch of object modules (*.obj files) into an own file which usual has a .lib file extension. another project now could link against that library and has all object modules linked same as if each single cpp (or c) file was compiled with the own project build.

because of this the second application instance from the static library was inserted to the executable additionally to the already existing one what was not tolerated at runtime cause each executable may have only one application object.

your static library should not have an application class object at all. instead it could access the one and only application object by calling AfxGetApp(). that returns a pointer to CWinApp which safely could be casted (dynamic_cast or c cast) to the derived application class.

Sara
alternatively to calling (and casting) AfxGetApp() you also could include a header where theApp was declared as extern.

// myapp.h
...

class MyApp :: public CWinApp
{
    ...
};

extern MyApp theApp;

Open in new window


you may search your headers if there isn't already such a declaration.

the "extern" keyword would allow to declare the global variable in a header which was included by multiple cpp files. the variable then was "defined" only once in the cpp file for the application class. otherwise the linker would complain because of duplicate symbols. but you could use the variable everywhere you included the header where the variable was declared as extern. actually you not even need to include a header but also could add the extern declaration to the cpp file where you want to use the variable.

Sara
Thanks -- I'l split the points -- Sara you helped a lot but Pepr's statement to place a breakpoint made me do it....