Question

I finished my small application and I am trying to make sure I have no memory leaks and no bugs. After looking at my Output I noticed that one of my functions is throwing a First-Chance exception, yet the function works great and does not crash.

The function calls another function in a CLR C++ DLL. I removed almost all code in the DLL function just for a test and the exception is still thrown so I know it is my EXE function that is the issue.

This is the code for the EXE function to call the DLL function.

LPCTSTR CHAXC0RDlg::Encrypt(LPCTSTR strValue)
{
    const char* Return;
    HINSTANCE hDLL = LoadLibrary(L"Library.dll");

    if(hDLL)
    {
        FARPROC hMethod = GetProcAddress(HMODULE (hDLL), "Encrypt");

        if(hMethod)
        {
            typedef const char* (*FunctionSig)(LPCTSTR);
            FunctionSig MethodCall = FunctionSig(hMethod);

            Return = MethodCall(strValue);
            FreeLibrary(hDLL);
        }
    }

    return _tcsdup(CString(Return));
}

This is the DLL function (as you can see I removed all code except for the code that generates a return value just as a test):

const char* Encrypt(LPCTSTR strPValue)
{ 
    String^ strValue = gcnew String(strPValue);
    string strReturn = (const char*)(Marshal::StringToHGlobalAnsi(strValue)).ToPointer();

    char* csValue = new char[strReturn.size()];
    strcpy(csValue, strReturn.c_str());
    return const_cast<const char*> (csValue);
}

The EXE function throws the exception on "const char* Return = MethodCall(strValue);" (I enabled breaking on this exception that is how I know).

Why exactly is this function throwing this exception?

Thank You!

EDIT

Update: My Character Set is UNICODE.

Update #2: From what I read in the suggestions and answers you are assuming this code does not work but it does. I enabled break on first-chance exceptions (and yes I do know what a first chance exception is) because I wanted this program to be good quality with all bugs gone. The code runs fine, I just wanted to figure out why the first-chance exception is being thrown because I like to be a better programmer. So I would like to fix this.

Update #3: I now have my code checking the values of hDLL and hMethod and both are not null when running this function. The problem seems to be in the call it self to the DLL. I am assuming the function signature is 100% correct for this code does work, it just throws a first-chance exception.

Update #4: I added the new changes to my function above as well added the DLL function code. The DLL function is a CLR C++ DLL. I removed all code in the DLL function as I stated already to make sure it was not my DLL.

Was it helpful?

Solution

It isn't clear from the snippet but it looks like you used __declspec(dllexport) on a managed function written in C++/CLI. The String^ and the Marshal class make that unequivocal.

Running managed code in an application that's otherwise entirely native is possible but it requires loading and initializing the CLR. There are a couple of ways to do that, I'm guessing you found the easiest way by chance. Using __declspec(dllexport) on a managed function forces the compiler to emit a stub that takes care of ensuring that the CLR is initialized and making the native-to-managed code transition.

So yes, the first time you call this exported function a wholeheckofalot of code executes behind your back. That's the time that the stub needs to load and initialize the CLR and load the assembly that contains your managed code. Seeing this code throwing and handling an exception isn't anything to worry about in general. There's little you can do about it anyway, you don't have the source code for this. You can make it less of an accidental event by hosting the CLR yourself. That takes a chunk of COM code, not so sure it is worth the cost.

From the clear evidence you provided that this doesn't actually cause a problem, this is feature, not a bug. Do note that you can trigger a real, unhandled exception with this kind of code. If the managed code throws a managed exception, it is common in managed code, then you'll get hammered by a Windows SEH exception with exception code 0xe0434f4d. That's invariably bad, you can use the __try and __catch keywords to catch it but you can't get a decent diagnostic for it since all the info about the managed exception is gonzo by the time the stack unwinds back to your code.

OTHER TIPS

  • Is the function signature 100% correct? Or is there a calling convention declaration missing? (such as WINAPI, STDCALL). Not likely the cause of your problem, but gets oyu in trouble otherwise (see TONT)
  • What is the exception? Tell your debugger to break if an exception is thrown (in my Visual Studio, it's Debug/Exceptions, enable "thrown" for ... well, all of them.
  • You are probably usign the API wrong (but that would manifest only later)
  • Is the input string valid? Does it happen for all values?

You will see something like "C++ exception" or "Access violation", and additional diagnostic information (if you are lucky).

There is a little chance that this first-chance exception is "normal" - i.e. it always happens for valid input. That's rare though, as the normal execution path should not throw exceptions.


Return value:

If the returned value is in a static/internal buffer inside the DLL (doesn't need to be freed), it becomes invalid when the DLL is unloaded.

If the return value is dynamically allocated by the DLL (e.g. DLL does new[] or malloc or _tcsdup), the DLL must also free the string, otherwise the string will leak. Do not free the string in the caller, as the DLL and the caller may or may not use different heaps.

Check the documentation for the DLL, it should say who needs to free the returned pointer, and how, and/or how long the returned pointer is valid.

The exception is thrown only the first time you call your exported function from the DLL. It is related to loading/initializing CLR for the first time and does not have anything to do with your code (happens before your code has a chance to execute). Subsequent calls to Encrypt do not generate this exception. Seems safe to ignore it.

It's not clear which 'Character Set' is used in your project (See Configuration Properties/General). You use L macro in 'LoadLibary' and not using it in 'GetProcAddress'.

HINSTANCE hDLL = LoadLibrary(L"Library.dll");
FARPROC hMethod = GetProcAddress(HMODULE (hDLL), "Encrypt");

Try to use _T macro instead:

HINSTANCE hDLL = LoadLibrary(_T("Library.dll"));
FARPROC hMethod = GetProcAddress(HMODULE (hDLL), "Encrypt");

it will put 'L' for you due to your project settings.

EDIT:

try

_declspec( dllexport ) const char* Encrypt(LPCTSTR strPValue)
{
...
}

and make sure that your module definition file contains

LIBRARY      "Library"

EXPORTS
    Encrypt @1

SECTIONS

 .data READ WRITE

also not why not use

const char* Encrypt(char* strPValue)

?

I put your code on VS2010, the caller (EXE) is C++ Console app. And the C++/CLI DLL is built with V90 tool set, but I didn't see any first chance exception being thrown.

I'm pretty sure that you had _declspec( dllexport ) in your header file, but I'm not sure how you defined it. Mine is like this.

extern "C"
{
    __declspec(dllexport) const char* Encrypt(LPCTSTR strPValue);
}

And no module definition file (.def). Can you tell me what is shown on your output window?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top