tags:

views:

296

answers:

3

I have implemented a DLL including DllMain() entry function:-

BOOL APIENTRY DllMain( HMODULE hModule,
  DWORD  ul_reason_for_call,
  LPVOID lpReserved
  )
{
    case DLL_PROCESS_ATTACH:
    /* here im doing file memory mapped through CreateFileMapping() API 
       and using it through MapViewOfFile() API
       storing some data structure in the file mapped area */
    ...
    case DLL_THREAD_ATTACH:
    ...
    case DLL_THREAD_DETACH:
    ...
    case DLL_PROCESS_DETACH:
    /* Here unmapping first through UnmapViewOfFile() API
       then tries to access the stroed data structure which is illegal 
       as we have already closed the file mapping
       This is the buggy code. The order should be first access the mapped memory 
       region and then unmap it */
       cout <<" some message"<<endl;
    ...

}

Unfortunately i made a mistake in DLL_PROCESS_DETACH case and accessing illegal memorey (access violation).

I made a sample program which loads the library using LoadLibrary() function, uses the library function and finally call FreeLibrary() and return.

When i executed this program, i didnt get any error message. But if i remove FreeLibrary(), in that case the DLL_PROCESS_DETACH case is executed implicitly and this time it gives error dialog box mentioning that there is access violation.

Why calling FreeLibrary() suppress this error? OR internally it handles this exception? What is suggested way.

Update: I have added details for ATTACH and DETACH. Probably it will help why i am not clear about the behavior observed. With FreeLibrary() call, i didnt get any error message but the cout message was not displayed. It seems crashed too but not being bnotified. But if i remove FreeLibrary(), in that case the DLL_PROCESS_DETACH case is executed implicitly and gives access violation dialog box. Ideally in former case as well, it should display the error. So i am guessing the FreeLibrary() suppresses this access violation error.

A: 

At the time of calling FreeLibrary, other parts of your program were all mapped into your virtual memory space. If your dll was freed automatically after other parts of your program had already been shut down, then fewer parts of your program were still mapped into your virtual memory space.

So at the time you called FreeLibrary, your bug in the DLL_PROCESS_DETACH case probably accessed memory that was in use by some other part of your program.

Windows programmer
Lets assume that in DLL_PROCESS_DETACH i have free the memory and then accessing it. So what you are saying is not the case here.
Adil
Perhaps you should post your actual code, so we wouldn't have to guess?
jeffamaphone
Adding complete source will be too big. i have added some details in the post. Please see, hope it helps my doubt.
Adil
A: 

just use the f***g debugger dude, if you want to be a programmer, better get used to it :)

Bartosz Wójcik
+2  A: 

The MSDN page for DllMain has a quote that might help explain what is happening to you.

When handling DLL_PROCESS_DETACH, a DLL should free resources such as heap memory only if the DLL is being unloaded dynamically (the lpReserved parameter is NULL). If the process is terminating (the lpvReserved parameter is non-NULL), all threads in the process except the current thread either have exited already or have been explicitly terminated by a call to the ExitProcess function, which might leave some process resources such as heaps in an inconsistent state. In this case, it is not safe for the DLL to clean up the resources. Instead, the DLL should allow the operating system to reclaim the memory.

So if you are calling FreeLibrary it's essentially a clean shutdown. Everything is in a valid state still. Any threads the Dll created are still around. All its memory is still around.

But if you just close the program (and don't call FreeLibrary) then it's more like an emergency shutdown (think crashing). Your Dll gets notified by the OS rather than the app. If this is the result of a crash then hoping memory is still valid isn't a great idea. And the stack is gone anyway.

So my guess is you are running into this problem because non-freed libraries are unloaded differently.

ProgramMax
What you are sayign is true but in my case its still not clear to me. i have added some details for ATTACH and DETACH case in the post. Please see, hope it helps my doubt. in DETACH case the case code gets executed irrespective whether OS is notifying the DETACH case or application itself. The thing is illegal memory access will happen in both situation.
Adil
I just looked at your changes. Could you show me which line the access violation happens on? Although, even if you show me chances are my response will be "That object you are accessing is no longer in valid memory." (Obviously...that's what an access violation is) :D I read a great post about this a little while back: It boiled down to saving a shadow copy of your file (kind of like how Word does). That way if your app crashed or the power goes out things aren't lost. But more importantly, it lets you just crash. Things will be graceful by design. Hope this helps.
ProgramMax
Butmy question still unanswered :) there is no difference in the code execution as i mentioned i did unmap and then tries to access the file mapped memory which is illegal. in case of FreeLibrary(), the next statement after accessing the memory location was not executed and silently program executed. in case of implicit call to DETACH, access violation error dialog box appears and then only i realized. So my point why the same dialog box was not appear in FreeLibrary() call. You cannot say that even after unmapping, the memory access is legal in that case :)
Adil
Oh wait, apparently I missed that part. You mean there is an access violation in both cases. But it doesn't say anything about the access violation in the FreeLibrary case? Hrmm I'm not sure about that...that's strange. Also strange to silently ignore that line and continue. Are you ignoring the return error code? That would make sense why it silently ignores and continues.
ProgramMax
Now you got it right :) But not sure why the access violation error not being popped up in case of FreeLibrary() call. No I am not ignoring return code. FreeLibrary return true in the buggy DETACH case code.
Adil