Does a standard DLL stay in memory?
|
|
Thread rating:  |
Greg Lovern - 15 Jun 2009 19:50 GMT In VB6, if I declare a function in a standard DLL with "Declare Function" (etc.), and then in the code make a call to that function in the standard DLL, does the DLL stay in memory until the VB application is closed?
Or is the standard DLL unloaded after each call to it?
Thanks,
Greg
Nobody - 15 Jun 2009 20:05 GMT > In VB6, if I declare a function in a standard DLL with > "Declare Function" (etc.), and then in the code make a call to that > function in the standard DLL, does the DLL stay in memory until the VB > application is closed? > > Or is the standard DLL unloaded after each call to it? It stays loaded. However, I think you can control when its loaded and unloaded by specifically calling LoadLibrary() before using any function in it, and when you no longer need it, call FreeLibrary().
Kevin Provance - 15 Jun 2009 22:35 GMT | It stays loaded. However, I think you can control when its loaded and | unloaded by specifically calling LoadLibrary() before using any function in | it, and when you no longer need it, call FreeLibrary(). That's an interesting approach.
If I use LoadLibrary to load a standard DLL, would a standard declaration use that loaded instance or load it's own? What if that DLL injects itself into a different process? Would FreeLibrary unload that as well? I was under the working assumption it did not until the process it was loaded in closed.
Karl E. Peterson - 15 Jun 2009 22:52 GMT >| It stays loaded. However, I think you can control when its loaded and >| unloaded by specifically calling LoadLibrary() before using any function in [quoted text clipped - 4 lines] > If I use LoadLibrary to load a standard DLL, would a standard declaration > use that loaded instance or load it's own? That module will only load once into a given process.
> What if that DLL injects itself into a different process? That'd be a different process, and those are distinct in Win32.
> Would FreeLibrary unload that as well? No way.
> I was under the working assumption it did not until the process it was > loaded in closed. That's how VB was designed. It'll call LoadLibrary if it doesn't find the module needed when needed, then call FreeLibrary against all on shutdown. This method would sidestep that. You could test it easily enough, with EnumProcessModules. But if you don't explicitly call it outside a Load/FreeLibrary pair, it shouldn't load on its own, so therefore it can't unload on its own either.
 Signature .NET: It's About Trust! http://vfred.mvps.org
Nobody - 16 Jun 2009 10:33 GMT >| It stays loaded. However, I think you can control when its loaded and > | unloaded by specifically calling LoadLibrary() before using any function [quoted text clipped - 9 lines] > under the working assumption it did not until the process it was loaded in > closed. After some research the approach that I described won't work. However, an alternative is to enumerate the modules by using toolhelp functions, such as Module32First/Module32Next, or EnumProcessModules, and call FreeLibrary on the DLL handle. However, if VB keeps internal information about the DLL, you may get unpredictable behavior if you called any function in that DLL after calling FreeLibrary.
When LoadLibrary is called, the DLL is loaded if not loaded already and a reference counter for the process is incremented, and when FreeLibrary is called, it's decremented. Once the reference count for the process reaches 0, the DLL is unloaded from the address space of that process.
Karl E. Peterson - 16 Jun 2009 19:48 GMT > After some research the approach that I described won't work. Huh? It's certainly "worked" for me. Different definitions of "work"?
 Signature .NET: It's About Trust! http://vfred.mvps.org
Nobody - 16 Jun 2009 21:14 GMT >> After some research the approach that I described won't work. > > Huh? It's certainly "worked" for me. Different definitions of "work"? Try this sample: Add two command buttons, the first loads the library and call a function in it, and the other frees it. Use Process Explorer to see loaded DLL's. In VB6+SP5 on XP+SP2, the DLL remains loaded in the process even after calling FreeLibrary, which returns Success.
Output:
LoadLibrary returned 2115895296, LastDllError = 0 API function returned 1, LastDllError = 0 FreeLibrary returned 1, LastDllError = 0
' Form1 code
Option Explicit
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" ( _ ByVal lpLibFileName As String) As Long Private Declare Function FreeLibrary Lib "kernel32" ( _ ByVal hLibModule As Long) As Long Private Declare Sub OutputDebugString Lib "kernel32" Alias _ "OutputDebugStringA" (ByVal lpOutputString As String)
Private Declare Function IsValidURL Lib "URLMON.dll" (ByVal pbc As Long, _ ByVal szURL As String, ByVal dwReserved As Long) As Long
Private hLibModule As Long
Private Sub Command1_Click() Dim ret As Long
hLibModule = LoadLibrary("URLMON.dll") OutputDebugString "LoadLibrary returned " & hLibModule & _ ", LastDllError = " & Err.LastDllError ret = IsValidURL(0, "http://www.cnn.com", 0) OutputDebugString "API function returned " & ret & ", LastDllError = " _ & Err.LastDllError End Sub
Private Sub Command2_Click() Dim ret As Long
ret = FreeLibrary(hLibModule) hLibModule = 0 OutputDebugString "FreeLibrary returned " & ret & ", LastDllError = " _ & Err.LastDllError End Sub
Scott Seligman - 16 Jun 2009 22:05 GMT >>> After some research the approach that I described won't work. >> [quoted text clipped - 4 lines] >loaded DLL's. In VB6+SP5 on XP+SP2, the DLL remains loaded in the process >even after calling FreeLibrary, which returns Success. That's expected. From MSDN for FreeLibrary:
] This function decrements the reference count of the loaded DLL module. ] ] When the reference count reaches zero, the module is unmapped from ] the address space of the calling process and the handle is no longer ] valid.
So, your call to FreeLibrary won't unload the DLL since the reference count is presumably still 1 from VB's call to LoadLibrary. You might be able to unload the DLL by having an unbalanced number of FreeLibrary calls, but that's a hack at best, and will probably cause VB to blow up if you call into the DLL again.
 Signature --------- Scott Seligman <scott at <firstname> and michelle dot net> --------- For of all sad words of tongue or pen, the saddest are these: 'It might have been.' -- John Greenleaf Whittier
Thorsten Albers - 16 Jun 2009 22:26 GMT Nobody <nobody@nobody.com> schrieb im Beitrag <#PDPI8r7JHA.1424@TK2MSFTNGP02.phx.gbl>...
> Try this sample: Add two command buttons, the first loads the library and
> call a function in it, and the other frees it. Use Process Explorer to see > loaded DLL's. In VB6+SP5 on XP+SP2, the DLL remains loaded in the process
> even after calling FreeLibrary, which returns Success. Of course VB has to do an internal call to LoadLibrary() in any case no matter how often and/or where you have added that call in your code. VB doesn't know anything about these 'manual' calls to LoadLibrary().
... = LoadLibrary(MyDLL) ' Ref. count +1 -> 1 <VB internal: LoadLibrary(MyDLL) ' Ref. count +1 -> 2 Call MyDLLFunction) FreeLibrary(MyDLL) ' Ref. count -1 -> 1
...
End of process requested <VB internal: FreeLibrary> ' Ref. count -1 -> 0
 Signature Thorsten Albers
albers (a) uni-freiburg.de
Karl E. Peterson - 16 Jun 2009 22:38 GMT > Nobody <nobody@nobody.com> schrieb ... >> Try this sample: Add two command buttons, the first loads the library and [quoted text clipped - 17 lines] > End of process requested > <VB internal: FreeLibrary> ' Ref. count -1 -> 0 That's the same conclusion I was arriving at. So the real utility of LoadLibrary is to call a function in a DLL that doesn't exist in the normal DLL search path (isn't in a predictable pre-compile location). I guess, to me, "worked" meant I was able to A) call the function and B) not blow up. <g>
So, I wonder what would happen in a case such as that? It doesn't fail, as it normally would when it can't find an entry point or the DLL itself. Does the 2nd LoadLibrary (VB's) succeed because we already loaded it? Hmmm...
 Signature .NET: It's About Trust! http://vfred.mvps.org
Thorsten Albers - 16 Jun 2009 23:34 GMT Karl E. Peterson <karl@exmvps.org> schrieb im Beitrag <eMKRdrs7JHA.1196@TK2MSFTNGP03.phx.gbl>...
> So the real utility of LoadLibrary is > to call a function in a DLL that doesn't exist in the normal DLL search path (isn't > in a predictable pre-compile location). There are other situations where LoadLibrary() is usefull, e.g.: - Test, if a library can be loaded at all (otherwise one would have to catch the error thrown by VB when the call to one of its functions is done) - Check, if the library holds a certain function (GetProcAddress()) etc.
> So, I wonder what would happen in a case such as that? It doesn't fail, as it > normally would when it can't find an entry point or the DLL itself. Does the 2nd > LoadLibrary (VB's) succeed because we already loaded it? Hmmm... Do you mean using LoadLibrary() and Declare ... for the same DLL with different pathes? If so: On Windows with NT technology the two AFAIK would be handled different because due to a different path they are not regarded as two instances of the same DLL even if DLL 2 is just a copy of DLL 2. On Windows 9x AFAIK both would be handled as two instances of the same DLL because there only the file name matters, not the file path.
 Signature Thorsten Albers
albers (a) uni-freiburg.de
Karl E. Peterson - 16 Jun 2009 23:47 GMT > Karl E. Peterson <karl@exmvps.org> schrieb ... >> So the real utility of LoadLibrary is [quoted text clipped - 4 lines] > - Test, if a library can be loaded at all (otherwise one would have to > catch the error thrown by VB when the call to one of its functions is done) Yeah, good one, there.
> - Check, if the library holds a certain function (GetProcAddress()) > etc. Definitely done that before. eg, GetDiskFreeSpaceEx.
>> So, I wonder what would happen in a case such as that? It doesn't fail, as it >> normally would when it can't find an entry point or the DLL itself. Does the 2nd >> LoadLibrary (VB's) succeed because we already loaded it? Hmmm... > > Do you mean using LoadLibrary() and Declare ... for the same DLL with > different pathes? Not exactly. No path in the declare, but the DLL is off the standard LoadLibrary search path. So, you have to programatically find it, then do an explicit LoadLibrary on it. (eg, http://vb.mvps.org/samples/MultiOE/) Hmmmm, now that I look at that project again (hey, it's been five years! <g>), I guess I did do it a bit differently there. I actually just used LoadLibrary to make sure I'd found a good DLL, and then ChDir'd into that DLLs file before making the first call to it. That enabled VB's LoadLibrary to succeed, by bringing it into the search path.
> If so: On Windows with NT technology the two AFAIK would > be handled different because due to a different path they are not regarded > as two instances of the same DLL even if DLL 2 is just a copy of DLL 2. On > Windows 9x AFAIK both would be handled as two instances of the same DLL > because there only the file name matters, not the file path. Right, makes sense.
 Signature .NET: It's About Trust! http://vfred.mvps.org
Schmidt - 17 Jun 2009 18:40 GMT > I guess, to me, "worked" meant I was able > to A) call the function and B) not blow up. <g> [quoted text clipped - 3 lines] > entry point or the DLL itself. Does the 2nd LoadLibrary > (VB's) succeed because we already loaded it? Hmmm... Yep - it succeeds, because in case of the VB-attempt, which performs that "second, implicite" LoadLibrary - the function will internally try to find the requested module "in memory" first.
Olaf
Karl E. Peterson - 17 Jun 2009 21:19 GMT > "Karl E. Peterson" <karl@exmvps.org> schrieb ... > [quoted text clipped - 9 lines] > performs that "second, implicite" LoadLibrary - the function > will internally try to find the requested module "in memory" first. Yeah, okay, that makes sense.
 Signature .NET: It's About Trust! http://vfred.mvps.org
|
|
|