我有一个C++DLL。我们最初在Visual Studio 2005中开发了它,最近将它升级到了Visual Studio 2013。然后,此DLL调用Fortran DLL以实现某些功能(Fortran DLL由无法共享源代码的第三方开发人员提供)。最近,对于一些输入,对Fortran库的调用开始抛出一个异常:
First-chance exception at 0x1C00BA50 in Application.exe: 0xC0000005: Access violation executing location 0x1C00BA50.
仅当从Windows 7上Visual Studio 2013生成的可执行文件调用Fortran DLL时,才会发生此异常。当我用Visual Studio 2005可执行文件中的相同输入调用同一个Fortran DLL时,没有异常,Fortran DLL会产生正确的结果。此外,在Windows XP SP3上运行Visual Studio 2005解决方案也不会产生错误。
支持细节:
- 调用Fortran的C++DLL是一个32位x86 DLL
- Fortran DLL是针对DFort 6.1a构建的
- 在依赖性walker中,需要:DFORRT.DLL、MSVCRT.DLL和KERNEL32.DLL
- C++可执行文件是使用"Visual Studio 2013-Windows XP(v120_XP)"平台工具集为x86构建的
- 崩溃不会发生在Windows XP SP3上;它在32位和64位Windows7机器上都可以。我正在设置一个Vista环境在那里进行测试,但几天内不会有结果
如果有帮助,函数签名是:
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);
}
库加载方式:
m_funcDLL = ::LoadLibrary("DLLNAME.DLL");
此外,我们称之为:
FUNCTIONID pfnFUNC = nullptr;
pfnFUNC = (FUNCTIONID)GetProcAddress(m_funcDLL, "FUNCNAME");
if(pfnFUNC) {
try {
iErr = (*pfnFUNC)( args...);
}
}
args是静态数组和动态数组的混合体(尽管我们已经用C++11的std::array和std::vector进行了实验来传递信息;使用这两种容器类型会得到相同的错误)。
我们在构建中没有使用Unicode(目前这是一个愿望列表项),所以我们使用多字节字符集(尽管传入的数组都不是字符数组)。
我的主要问题是:有人知道Windows 7上Visual Studio 2013的二进制兼容性问题会导致这样的崩溃吗?有没有我应该看的东西我没有?
如果发生以下一种或多种情况,链接到不同版本的运行库(可能还有其他库)的DLL和使用DLL的代码有被破坏的危险:
- DLL的接口使用类/结构,其中的大小可能因运行库的版本而异。(一个不幸的成员可能就足够了)
- 没有在接口的同一侧分配/释放堆对象
- 有时人们会玩编译器关于对齐的设置。也许不同版本的编译器也会改变他们的"策略"
- 注意#pragma(pack,..)、__declspec(align())等
- 在VS的旧版本中,有"单线程"one_answers"多线程"版本的运行时库。混合使用未链接到同一类型库的DLL和应用程序可能会导致问题
- 头文件中的
#include <seeminglyharmlessheader.h>
,应用程序和DLL都可以看到,可能会有一些令人讨厌的惊喜 - 可能是其他编译器/链接器设置中的(未注意到的)更改,例如关于异常处理
我不能完全理解你在问题部分所说的32位/64位的内容。我不认为,混合这两种作品,但我也认为你没有尝试。