我正在使用Visual Studio Express 2013编写C ++应用程序。我的应用程序调用名为refprop.dll的模块。但是,对SETUPdll的调用有时会失败(大约一半的时间)。其他时候它完美地运作。我的代码是这样的。
在refprop1.h
中typedef void(__stdcall *fp_SETUPdllTYPE)(long &, char*, char*, char*, long &, char*, long, long, long, long);
fp_SETUPdllTYPE SETUPdll;
在Main .cpp
中#include <windows.h>
#include <stdio.h>
#include <iostream>
#include "refprop1.h"
// Some constants...
const long refpropcharlength = 255;
const long filepathlength = 255;
const long lengthofreference = 3;
const long errormessagelength = 255;
const long numparams = 72;
const long maxcoefs = 50;
int main(int argc, char* argv[])
{
// First create a pointer to an instance of the library
// Then have windows load the library.
HINSTANCE RefpropdllInstance;
RefpropdllInstance = LoadLibrary("C:\\Program Files (x86)\\REFPROP\\REFPROP.DLL");
//point the function
SETUPdll = (fp_SETUPdllTYPE)GetProcAddress(RefpropdllInstance, "SETUPdll");
//setup variables
long i, ierr;
char hf[refpropcharlength*ncmax], hrf[lengthofreference + 1],
herr[errormessagelength + 1], hfmix[refpropcharlength + 1];
i = 3;
strcpy_s(hf, "D:\\East101\\Adri\\devprojects\\theSeed\\RefProp\\fluids\\METHANE.FLD|ETHANE.FLD|BENZENE.FLD");
strcpy_s(hfmix, "D:\\East101\\Adri\\devprojects\\theSeed\\RefProp\\fluids\\HMX.BNC");
strcpy_s(hrf, "DEF");
strcpy_s(herr, "Ok");
//call the setup - this SOMETIMES throws an error: Unhandled exception.....
SETUPdll(i, hf, hfmix, hrf, ierr, herr, refpropcharlength*ncmax, refpropcharlength,lengthofreference, errormessagelength);
编辑: 我也注意到问题只出现在SETUPdll调用中。其他调用可以成功完成(但无意义,因为您需要先调用SETUPdll)。
还有什么方法可以调试dll本身/同行到那里发生了什么?
答案 0 :(得分:1)
关于代码的一些事情(我还从你的代码片段结束了main
函数):
在调用 Windows API (或任何其他)功能时,从不忽略返回代码,否则您可能最终难以找到问题,例如目前的一个。但在我们的案例中没有这样的错误。
我修改了一些常量(请参阅我的代码段中的注释)。在某些情况下,这也可能引发难以发现的问题,但这里的情况并非如此。
您的代码无效(当 Acces违规失败时),因为文件路径不正确。以下是它用于返回的错误:组件#2的打开文件中出现 [SETUP错误101]错误; filename =(ETHANE.FLD)。我通过指定完整路径来解决这个问题。
请注意,我还从NIST下载了其他代码,但它太复杂了,它需要我没有安装的东西,所以我专注于你的代码(我甚至将文件复制到相同的路径上以获得环境尽可能接近你的。)
关于 RefProp 的个人观点:我不知道它到底是什么,我知道它是一种不同化学物质的属性DB(大多数是有机化学的一部分),但是编程术语:
不确定 refrpop1.h 是如何诞生的:
如果它是后者那么它没关系,但如果是前者,那真的很糟糕因为(我在这里只列举了最困扰我的前两项):
SETUPdll
做了什么/应该做什么,我不知道论点/应该是什么,例如我强烈认为只有错误文本(herr
)是一个输出参数(如果我的假设是正确的,那么所有其他参数应该是const char *
)所以,回到你的代码(带有更正):
#include <windows.h>
#include <stdio.h>
#include <iostream>
#include "refprop1.h"
// Some constants...
const long refpropcharlength = 255;
const long lengthofreference = 3;
const long numparams = 72;
const long maxcoefs = 50;
const long ncmax = 20;
const long filepathlength = MAX_PATH; //Windows defines this constant (260)
const long errormessagelength = 255 + filepathlength; //Error message contains an error text + a filename
const long hflength = filepathlength * ncmax + ncmax - 1; //ncmax files + (ncmax - 1) separators ("|")
const long hfmixlength = filepathlength;
int main(int argc, char* argv[])
{
// First create a pointer to an instance of the library
// Then have windows load the library.
HMODULE RefpropdllInstance = NULL;
if ((RefpropdllInstance = LoadLibrary("C:\\Program Files (x86)\\REFPROP\\REFPROP.DLL")) == NULL) {
printf("Error [%d] loading lib\n", GetLastError());
return -1;
}
//point the function
if ((SETUPdll = (fp_SETUPdllTYPE)GetProcAddress(RefpropdllInstance, "SETUPdll")) == NULL) {
printf("Error [%d] getting func\n", GetLastError());
FreeLibrary(RefpropdllInstance);
return -2;
}
//setup variables
long i = 3, ierr = 0;
char hf[hflength + 1], hrf[lengthofreference + 1],
herr[errormessagelength + 1], hfmix[hfmixlength + 1];
strcpy_s(hf, "E:\\East101\\Adri\\devprojects\\theSeed\\RefProp\\fluids\\METHANE.FLD|E:\\East101\\Adri\\devprojects\\theSeed\\RefProp\\fluids\\ETHANE.FLD|E:\\East101\\Adri\\devprojects\\theSeed\\RefProp\\fluids\\BENZENE.FLD");
strcpy_s(hfmix, "E:\\East101\\Adri\\devprojects\\theSeed\\RefProp\\fluids\\HMX.BNC");
strcpy_s(hrf, "DEF");
strcpy_s(herr, "Ok");
//call the setup - this SOMETIMES throws an error: Unhandled exception.....
// (long &, char*, char*, char*, long &, char*, long, long, long, long);
SETUPdll(i, hf, hfmix, hrf, ierr, herr, hflength, hfmixlength, lengthofreference, errormessagelength);
if (ierr != 0) {
char aux[errormessagelength + 40];
sprintf(aux, "Error [%d] calling `SETUPdll`(%d): %s\n", ierr, strlen(herr), herr);
OutputDebugString(aux);
printf(aux);
}
FreeLibrary(RefpropdllInstance);
printf("Done\n");
return 0;
}
试验:
hf
没有完整路径时(所以SETUPdll
返回错误101),故障更频繁;使用正确的路径,我连续100次运行(多次)而没有遇到它。我不是说这是一个规则,它可能只是巧合。main
移动到另一个func并在循环(1000次迭代)中从main
调用它,也是多次,但失败没有出现。所以,最后一个问题:
我有一个明确的答案,为什么程序因Access违规(segfault)而失败?
答案是:否。
但是我已经检查了 REFPROP.DLL 依赖项,并且只有2个: KERNEL32.DLL 和 USER32.DLL (没有< EM> MSVCR * .DLL )。这意味着它已静态链接到 VC运行时(或任何C运行时等效项)。另一方面,您的可执行文件也有自己的VC运行时(如何链接到它并不重要)。
因此,您的可执行文件中有2个C运行时(一个在exe中,一个在dll中)。 C运行时任务之一是内存管理:如何分配/取消分配内存(指针)(检查malloc / free函数)。在某些情况下(如果dll代码和exe代码不在“同步”中),您最终可能会从一个运行时分配指针并从另一个运行时解除分配,这可能会导致我们在这里遇到的行为。
答案 1 :(得分:0)
@CristiFati给出了一个非常好的解释。
作为一种解决方法(丑陋但对我有用):
RefpropdllInstance是一个类(RefPropPack)的成员,它处理设置和调用。 我现在正在捕获访问冲突错误(请参阅此处的详细信息:http://msdn.microsoft.com/en-us/library/1deeycx5(v=vs.80).aspx)。我已经尝试重新加载dll(FreeLibrary(),将指针设置为NULL,重新加载和重新映射函数并调用SETUPdll)但是没有解决问题。因此,当错误发生时,我只是删除RefPropPack对象并重新安装/设置它。它可能需要不止一次尝试,但最终会成功。