vc++8.0 bug: access violation upon call of any CImageList methods

I have sucessfully imported and compiled a complex MFC 6.0 project from vc++6.0  into vc++ 8.0 (MFC 8.0). It contains several subprojects (libs and dlls). In vc++ 6.0 those project linked MFC6.0 statically and after I imported it to vc++ 8.0 I set the linkage of MFC8.0 to "shared". However when I try to compile and link the project in vc++ 8.0 in release mode (debugmode works fine) I get an acess violation in afxcomctl32.inl. This happnes whenever I call any of the CImageList methods. When I comment out all lines that call mehtods of CImageList everything work fine in release mode too.

When I look at the disassembly the crash pattern is always the same. The access violation always happens after a call of AfxGetModuleState and before a call to CComCtlWrapper::_ImageList_XXX

disassembly:

004DE7F5  call        AfxGetModuleState (49CE2Ah)
004DE7FA  mov         eax,dword ptr [eax+90h] // it is always 90h added
004DE800  mov         ecx,dword ptr [eax]  <------------ access violation !!!!
004DE802  call        CComCtlWrapper::_ImageList_GetIcon (49E158h)
( the last line can be interchanged by  CComCtlWrapper::_ImageList_GetImageCount (49A805h) or any other call to CImageList mehtods )

registers:

EAX = 00000004 EBX = 00180940 ECX = 781FF81B EDX = 782BA9DC
ESI = 7821A936 EDI = 00000000 EIP = 004DE800 ESP = 0012BB04
EBP = 0012BB5C EFL = 00000206

Can anyone explain what is going on here and give me hints how to solve this problem What does AfxGetModuleState do What is afxcomctl32.inl   What could be obvious places to look for Is this a know bug in vc++ 8 I have found a bug in vc++ 8.0 that is STILL UNRESOLVED  that somehow looks a little similar to mine:  http://forums.microsoft.com/MSDN/ShowPost.aspx PostID=132410&SiteID=1
Nevertheless the problem described there and the workaround suggested does not fit here, since all of my projects have the allignment set to default and nowhere in my project I see any #pragma pack directives.

Also I wonder what the purpose of  the addition of 90h in this line is:
004DE7FA  mov         eax,dword ptr [eax+90h]



Answer this question

vc++8.0 bug: access violation upon call of any CImageList methods

  • Brian Harrison

    Believe me, it took quite a while to find the solution to this, a lot of trial and error, and only after that, I found someone had already reported it on the product feedback center.  It's a killer for every user of MFC.


    Weird. All of our apps are MFC and I'm using VS2005 and haven't hit this issue.

    Then again, I don't use CImageList either, I prefer to stick with STL containers.

  • Dan Cowell

    You may not believe it, but in fact this is the problem.  I had the exact same symptoms.  Regardless of your alignment, you must put

    #pragma pack(push, 8)

    and

    #pragma pack(pop)

    around every single inclusion of MFC header files (this includes afxwin.h, afx.h, etc).  The best place is in your stdafx.h files.   Do a find in files to make sure every last MFC header inclusion is wrapped by those pragmas. 

    Try it, you'll see that it fixes the problem.

     


  • pharita

     bitbonk wrote:
    I have insterted #pragma pack (show) all over the place in my project. It always shows 8. I have also tried to add a #pragma pack (show) into afxcomctl32.h but now I get a fatal error RC10056. Even when I remove all changes from that header I still get this error now. I cannot compile at all anymore now.

    Try cleaning or building into a brand new folder.  Something must be corrupted (sounds like resources).  Try deleting opt, ncb, and aps files from your build folders

    Can you explain how to compile MFC Wouldn't that require me to have the MFC source code

    You do have the source code.  You can compile MFC by using the provided makefiles.  Just launch a Visual Studio command prompt and build using the second half of the instructions here

    http://blogs.msdn.com/michkap/articles/478235.aspx

    starting at "Building MFC 8.0 Unicode version with MSLU" (for your purposes, ignore any information relating to modifying for unicows.lib). Actually, step 5 is all you really need to do.  I would only recommend this to diagnose the packing problem, and not redistribute the rebuilt versions.


  • -Q

    The problem starts with that I am not really sure what actually can be considered as MFC headers. Can I safely assume that all .h files that start with afx are MFC headers Or are there any others I have to decorate with #pragma pack as well

    My projects have 5 stdafx.h. All fo them include a lot of afx*.h plus a lot of custom headers. One of the projects is a lib and does not have a stdafx.h. What I tried so far is to put #pragma pack (push,8) at the beginning of all stdafx.h and #pragma pack(pop) at the end of each stdafx.h. That did not change anything.

    Could you assitst me in understanding what is actually going on here I still have the feeling that I did not quite understand this bug.
    In the release version of MFC80.DLL  the structure alignment when building afxcomctl32.h is 8 bytes regardles of what byte allignment I have set in my projects How did you find that out Where in the
    afxcomctl32.h is the allignment changed from 4 (the default in MFC) to 8
    Also why can this error not be reproduced in a standard MFC project   I have to change the allignment to 1 byte in the project settings to make this bug appear.  This differs from my current project where I can set the allignment to what I want - the access violation always appears.

    Also in the error in the standard MFC project occurs right as startup of the application . In my case the the access violation appears only at the moment when the actual CImageList methods is called. 

    Let us look at the dissasembly again:
    004DE7F5  call        AfxGetModuleState (49CE2Ah)

    AfxGetModuleState returns a pointer to thread-local storage for a struct called AFX_MODULE_STATE that stores information about the current running module.

    004DE7FA  mov         eax,dword ptr [eax+90h]

    at the offset of 90h *should* be
    AFX_MODULE_STATE::m_pDllIsolationWrappers wich is of type CDllIsolationWrapperBase**.

    004DE800  mov         ecx,dword ptr [eax]   <--- access violation

    the dereferenciation of the above did not work out. .


    So what did actually happen here Did
    AfxGetModuleState return a invalid pointer Is the 90h offest incorrect Or ist the structure returned by AfxGetModuleState() "broken".



  • hussain hammad

    The problem starts with that I am not really sure what actually can be considered as MFC headers. Can I safely assume that all .h files that start with afx are MFC headers Or are there any others I have to decorate with #pragma pack as well

    Yes, all headers with AFX in their name, that's the rule of thumb I used.


    My projects have 5 stdafx.h. All fo them include a lot of afx*.h plus a lot of custom headers. One of the projects is a lib and does not have a stdafx.h. What I tried so far is to put #pragma pack (push,8) at the beginning of all stdafx.h and #pragma pack(pop) at the end of each stdafx.h. That did not change anything.

    regardless of whether they are in stdafx or not, you must put pragmas around them.  and be sure to do a rebuild all.  and all static libraries as well. 


    Could you assitst me in understanding what is actually going on here I still have the feeling that I did not quite understand this bug.
    In the release version of MFC80.DLL  the structure alignment when building afxcomctl32.h is 8 bytes regardles of what byte allignment I have set in my projects How did you find that out Where in the afxcomctl32.h is the allignment changed from 4 (the default in MFC) to 8

    I actually inserted a pragma into the afxcomctl32.h file to report the level of packing currently being used (using #pragma pack(show) ), then actually rebuilt the MFC libraries and DLLs and saw what the results were as the files were being built.   


    Also why can this error not be reproduced in a standard MFC project   I have to change the allignment to 1 byte in the project settings to make this bug appear.  This differs from my current project where I can set the allignment to what I want - the access violation always appears.

    Not sure about this.  I have had good luck reproducing it by changing the pack level of the project to 2 from 8.  I recommend scattering some #pragma pack(show) throughout your code to see where things are going wrong. 

    Also in the error in the standard MFC project occurs right as startup of the application . In my case the the access violation appears only at the moment when the actual CImageList methods is called. 

    Let us look at the dissasembly again:
    004DE7F5  call        AfxGetModuleState (49CE2Ah)

    AfxGetModuleState returns a pointer to thread-local storage for a struct called AFX_MODULE_STATE that stores information about the current running module.

    004DE7FA  mov         eax,dword ptr [eax+90h]

    at the offset of 90h *should* be
    AFX_MODULE_STATE::m_pDllIsolationWrappers wich is of type CDllIsolationWrapperBase**.

    004DE800  mov         ecx,dword ptr [eax]   <--- access violation

    the dereferenciation of the above did not work out. .


    So what did actually happen here Did
    AfxGetModuleState return a invalid pointer Is the 90h offest incorrect Or ist the structure returned by AfxGetModuleState() "broken".

    the common control wrapper structure is messed up, because ints in the structure are being aligned on 8 byte boundaries, and because of inlining, everything is in the wrong place (not aligning with what was built in the DLL)

    Believe me, it took quite a while to find the solution to this, a lot of trial and error, and only after that, I found someone had already reported it on the product feedback center.  It's a killer for every user of MFC. 

    Another much simpler solution would be to change afxcomctl32.h and insert some #pragma pack (push, 8), and #pragma pack (pop) around its body (top and bottom).  But I didn't want to change any system files as I don't want the hassle of rolling out that file to many different developer workstations. 


  • au55ie

    I have now tried to to surround each and every include of a .h file that starts with 'afx' with #pragma pack (push,8)
    and
    #pragma pack (pop)

    I still get the very same access violation.


  • nielaldous

    Ok, I have narrowed down (and almost solved)  the problem so far:
    None of the hints and suggestions by Ted worked out for me, so it seems that in this case the described access violation has nothing to do with alignment.
    I manged to eliminate the access violation by calling all the Mehtods of CImageList that later cause access violations BEFORE they get called from within classes that belong to a static lib project. Infact they do not need to be actually called, they just need to be defined once outside the lib. So in the OnInitDialog of my initial MFC Dialog I put:
    if (false)
    {
    // "call" all CImageList methods that cause accessviolations here
    }

    Once you do this, there won't be any access violations anymore.
    For your info: All the calls that caused access violations reside in a static lib (with MFC linked as shared dll). This lib project was imported from vc++ 6 and linked MFC statically originally. This lib also takes care of laoding a dll via LoadLibrary().

    Now allthough I have a working workaround, I still would love to understand this bug and where it comes from. I would be happy if you have hints or any sort of input for me where to look.



  • Mohammed Mudassir Azeemi

    I overstated it, it is really only a problem for users that have packing set in their projects other than 8 bytes.
  • solomonk

    I just wanted two share to discoveries I have made:

    1. After decorating all afx*.h  includes with #pragma pack (push,8) and #pragma pack (pop) there is one Method of CImageList I can now call sucessfully: CImageList::Add() does now not cause an access violation aynmore. However all other Methods (i.e. ExtractIcon, GetImageCount ) still cause that acess violation. EDIT: this is incorrect the reason why I could call .Add() successfully here was beacuse I accidentally added a call to .Add() in my MFC Dialog. That's how I discoverd the workaround posted below.

     2. As a result of an Buttonpress some dlls get loaded via LoadLibrary. And some classes in that dll get instanciated via exported functions. (GetProcAdress). Now I discovered that I can call almost all (the only one I have found causing still an access violation is CImageList::ExtractIcon) methods of CImageList without causing any access violations as long as I don't press that button.

     



  • Bulky

    I have insterted #pragma pack (show) all over the place in my project. It always shows 8. I have also tried to add a #pragma pack (show) into afxcomctl32.h but now I get a fatal error RC10056. Even when I remove all changes from that header I still get this error now. I cannot compile at all anymore now.

    I actually inserted a pragma into the afxcomctl32.h file to report the level of packing currently being used (using #pragma pack(show) ), then actually rebuilt the MFC libraries and DLLs and saw what the results were as the files were being built.

    Can you explain how to compile MFC Wouldn't that require me to have the MFC source code


  • Martin Koster

    Everyone, please check your all vcproj files for StructMemberAlignment options (using find in files).  They may be left over, or only set for specific files. 

    The only way this bug will occur is if the StructMemberAlignment is something other than 8, or something else is bringing in other than 8 like a #pragma pack or #pragma pack( push, )

    Adding #pragma pack (push, 8) to the top of afxcomctl32.h (after #pragma once) and #pragma pack(pop) to the bottom (before final #endif) will work as well.

     

     


  • hpux

    @Ted But trhis doen't make it neccesary that you need to rebuild the MFC! If there is a packing problem, the problem is not inside the DLL code and not in the headers. If there is a problem, it can be solved on the source side with some pushs and pops!

  • Salvador Cadena

    I have put a #pragma pack (show) at the top of afxcomctl32.h and when I link and compile my projects it always shows 8. So in case "Ted's" bug applies here there should be at least one Message showing another alignment when I compile my projects. Is that correct

    Also I have searched my entire solution for "#pragma pack" it only showed up a "#pragma pack (8)" in ipl.h (intel jpg library) and ipl.h (intel/image processing library).



  • Kishore Annavarapu

    I have the exact same problem, a crash at CImageList.Add() in release mode only.  I also use the default byte alignment (8).  I have tried putting the #pragmas around every MFC header file include.  But I still get the same crash.  My app has about 75 DLLs, so I am in the process of double-checking that I found all of the MFC includes.  But I am stumped also.  The workaround of adding #pragmas doesn't seem to be working for me either.

    Are there other workarounds   Any other options besides using the CImageList class



  • vc++8.0 bug: access violation upon call of any CImageList methods