3

I must be missing something here; going crazy.. I'm using VS2010 C#, developing a Windows Form application in C#. In the same solution I have a c++ dll project that outputs it's DLL to the same "/bin/" folder as the C# executable. I'm looking at the folder and the file is definitely there. I even used the following to make sure it existed at run-time:

// yep.. it's there...
string s = System.IO.Directory.GetCurrentDirectory() + @"\Foo.dll";
System.Diagnostics.Debug.Assert(System.IO.File.Exists(s));

my DLL has this:

extern "C" __declspec(dllexport) int test_func();

which I confirmed with a DLL explorer utility to have the correct name inside. The function itself does nothing but "return 4;"

C# code is:

[DllImport("Foo.dll")]
private static extern int test_func();

I get this error:

An unhandled exception of type 'System.DllNotFoundException' occurred in .exe

Additional information: Unable to load DLL 'Foo.dll': Invalid access to memory location. (Exception from HRESULT: 0x800703E6)

Ben
  • 143
  • 2
  • 6

2 Answers2

2

The error is occurring when the framework calls LoadLibrary. That can be deduced from the error message:

Unable to load DLL 'Foo.dll'

The error code that is reported is a COM error code that wraps Win32 error code 998, aka ERROR_NOACCESS. The scenario that leads to a call to LoadLibrary throwing ERROR_NOACCESS is described here: http://support.microsoft.com/kb/196069

SYMPTOMS

The LoadLibrary() API may sometimes encounter an access violation while attempting to map a specified module into the address space of the calling process. In this event, LoadLibrary() returns a value of NULL and GetLastError() returns an error code of 998 (ERROR_NOACCESS). Back to the top | Give Feedback

CAUSE

The Windows NT status code STATUS_ACCESS_VIOLATION is mapped to the Win32 error code ERROR_NOACCESS. As a result, if the operating system loader encounters an access violation (exception C0000005) while mapping the specified DLL file image or executing the startup code, the loader will set the last error to 998 (ERROR_NOACCESS) and the LoadLibrary() function will fail with a return value of NULL. Back to the top | Give Feedback

MORE INFORMATION

When an access violation occurs anywhere in the startup code, the exception dispatcher detects whether the process that encountered this exception is being debugged. If so, this first chance exception is sent to the debugger.

To troubleshoot the LoadLibrary() failure, run the application under a debugger and enable first chance exception handling for the C0000005 Access Violation exception. If an access violation occurs when the LoadLibrary() function is called, the application will break into the debugger. The debugger's call stack can then be used to trace where the exception occurred. The stack trace should help you narrow down the actual problem related to the exception being encountered.

For information on how to enable first chance exception handling for the C0000005 Access violation exception, please refer to the debugger documentation.

In essence, your DLL is producing an access violation in its startup code. Many things could cause that and you'll need to do some debugging of the DLL. I suggest that you attempt to debug this from a native C++ host. It will likely be easier to debug the DLL that way.

As an aside, your function uses the cdecl calling convention, and once you get past the current hurdle, you'll need to modify your C# p/invoke to specify CallingConvention.Cdecl.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • I used DllImport[] on LoadLibrary from within my C# application and call it returned "0". ?!? I used the exact same path that I used with File.Exists() so I think this must be some kind of permissions problem.. – Ben Nov 25 '13 at 22:01
  • No. It returns `LoadLibrary` returns `0` when it fails. That indicates an error. If you include `SetLastError=true` in the `LoadLibrary` pinvoke you can call `Marshal.GetLastWin32Error` and it will return 998. It's not permissions. Your DLL's `DllMain` is raising an access violation. Your next step is to do exactly what I said. Debug this with a native host. Or work out how to enable unmanaged debugging from your C# host. – David Heffernan Nov 25 '13 at 22:03
  • Oh man I did not see this one coming... a global static class was accessing it's own "static std::map<>" member. But it appears that it was being accessed before the the member's definition. I guess it somehow had not initialized it's own values in time to be used by the constructor. I didn't even think that was possible! I reordered the code and now it works.. crazy. – Ben Nov 25 '13 at 22:40
  • Yes. Static initialization. Catches you out!! – David Heffernan Nov 25 '13 at 22:45
0

Assume you already saw this link.

Have you opened "foo.dll" with depends.exe to ensure you have all the dependencies satisfied?

Community
  • 1
  • 1
tobyb
  • 696
  • 9
  • 18
  • The DLL is doing nothing. It depends only on a couple stl template headers. I ran depends.exe and only got this: Error: At least one module has an unresolved import due to a missing export function in an implicitly dependent module. Error: Modules with different CPU types were found. I'm guessing it's complaining because the DLL is 32bit and I'm running Windows 7 x64. – Ben Nov 25 '13 at 21:58