Out of Memory Errors in SSIS When Loading 32 bit DLLs
Was speaking with a customer today about an issue where they were receiving “Out of Memory” exceptions when trying to load a 32 bit PostgreSQL ODBC driver from within an SSIS package.
When the package was run from the command line using Dtexec, all was fine. When the package was run from within the SSIS Catalog, the same package refused to run. They had presumed it was some issue to do with 32 bit vs 64 bit drivers. The customer resolved it by installing the latest 64 bit PostgreSQL ODBC drivers.
However, it’s important to know that when you see an “Out of Memory” error on attempting to load a 32 bit DLL, it usually doesn’t mean anything about memory at all.
Under the covers, in 32 bit Windows, loading an accessing a function in a DLL was performed by:
1. Making an API call to LoadLibrary() – this brought the DLL into memory if it wasn’t already present
2. Making an API call to GetProcAddress() – because the DLL could be located anywhere in memory, there was a need to locate the actual memory address of the procedure in the DLL in its loaded location
3. Making a call to the address returned by the GetProcAddress() call.
With my previous developer hat on, there are several places where I’ve seen this go wrong.
One is that people don’t check the return address from GetProcAddress(). It can return null if the procedure isn’t found. So someone who writes code that just immediately calls the address returned without checking if it is null, would end up generating the previous infamous “this program has performed an illegal operation and will be shut down” message that we used to see.
The less common problem was that LoadLibrary() had its own qwerks. The worst was that if it could not locate the DLL, the error returned was “Out of Memory”. I always thought that was one of the silliest error messages to ever come out of Windows, but it’s entirely relevant here.
When you see an “Out of Memory” error when attempting to load a 32 bit DLL, it’s time to check whether the DLL can be located by the process. The easiest (although not the cleanest) would be to make sure the DLL is in the GAC (global assembly cache).
2015-04-10