0
votes

I have a C++ DLL. We developed it originally in Visual Studio 2005 and recently upgraded it to Visual Studio 2013. This DLL then calls into a Fortran DLL for some functionality (the Fortran DLL is provided by a third party developer who cannot share source code). Recently, for some inputs, the call to the Fortran library has started throwing an exception:

First-chance exception at 0x1C00BA50 in Application.exe: 0xC0000005: Access violation executing location 0x1C00BA50.

This exception only occurs when the Fortran DLL is called from the Visual Studio 2013 generated executable on Windows 7. When I call the same Fortran DLL with the same input from the Visual Studio 2005 executable, there is no exception and the Fortran DLL produces correct results. Additionally, running the Visual Studio 2005 solution on Windows XP SP3 does not produce an error either.

Supporting details:

  • The C++ DLL that calls the Fortran is a 32-bit, x86 DLL
  • Fortran DLL is built against DFort 6.1a
  • In dependency walker, needs: DFORRT.DLL, MSVCRT.DLL, and KERNEL32.DLL
  • The C++ executable is built for x86 using the "Visual Studio 2013 - Windows XP (v120_xp)" Platform Toolset
  • The crash does not happen on Windows XP SP3; it does on both 32 and 64-bit Windows 7 machines. I am setting up a Vista environment to test there, but won't have results for a few days.

If it helps, the function signature is:

extern "C"
{
    typedef long (__stdcall *FUNCTIONID)
    (
    float* array1, 
    float* array2, 
    float* array3, 
    long& numItems, 
    long& numThings, 
    float* thingData, 
    float* thing2data,
    float& result, 
    long* resArray, 
    float* resArray2, 
    float* resArray3); 
}

The library is loaded by:

m_funcDLL = ::LoadLibrary("DLLNAME.DLL");

Additionally, we call this by:

FUNCTIONID pfnFUNC = nullptr;
pfnFUNC = (FUNCTIONID)GetProcAddress(m_funcDLL, "FUNCNAME");
if(pfnFUNC) {
    try {
        iErr = (*pfnFUNC)( args...); 
    }
}

The args are a mix of static arrays and dynamic arrays (although we have experimented with C++11's std::array and std::vector to pass things around; we get the same error using both container types).

We're not using Unicode on our builds (that's a wishlist item for now), so we're using Multibyte Character Sets (although none of the arrays passed in are char arrays).

The primary question I have is: Is anyone aware of any binary compatibility issues with Visual Studio 2013 on Windows 7 that would cause crashes like this? Are there things I should be looking at that I'm not?

1
Best don't use runtime library dependent types in your DLL interfaces. If DLL and using code link against different versions, there is trouble ahead. Also try not to transfer ownership of memory blocks. (malloc() on one side, free() on the other). - BitTickler
extern "C" on a long& looks fishy - user2249683
I'll look to see what equivalent types are for Fortran/C++ interfaces. It looks like the floats are okay (they map to REAL), and the longs are scary (the fortran interface specifies Integers). Would C++'s int be sufficient or should I use int_32? - Kevin K
extern "C" is about the linkage and name mangling. It says nothing about C vs C++. If it worked in other combinations of application/DLL, you can assume that both sides are "c++". - BitTickler

1 Answers

1
votes

DLLs and code using DLLs which are linked against different versions of the runtime library (and possibly other libraries) are in danger of breaking, if one or more of the following happens:

  • Interface to DLL uses classes/structures, where the size might differ depending on version of runtime library. (One unfortunate member might be enough).
  • Heap objects are not being allocated/freed at the same side of the interface.
  • Sometimes people play with compiler settings regarding alignment. Maybe different versions of compilers also change their "policy".
  • Look out for #pragma (pack,..), __declspec(align()) etc.
  • In older Versions of VS there were "single threaded" and "multi-threaded" versions of run time libraries. Mixing DLLs and Applications not linked against the same kind of library could cause trouble.
  • #include <seeminglyharmlessheader.h> in header files, seen by both application and DLL can hold some nasty surprises in stock.
  • Maybe an (unnoticed) change in other compiler/linker settings, e.g. regarding exception handling.

I could not fully follow the 32bit/64bit things you said in the question part. I don't think, mixing both works, but I also think you are not trying that.