c++ - 使用 refprop.dll 调用在访问冲突读取位置出现未处理的异常

标签 c++ visual-studio dll

我正在使用 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 本身/查看其中发生了什么?

最佳答案

关于代码的一些事情(我还结束了您代码段中的 main 函数):

  • 当调用 Windows API(或任何其他)函数时,永远不要忽略返回码,否则您可能会很难找到问题,例如当前的一个。但在我们的例子中没有这样的错误。

  • 我稍微修改了常量(请参阅我的代码片段中的注释)。在某些情况下,这也可能会引发难以发现的问题,但这里又不是这种情况。

  • 您的代码没有工作(当它没有因访问冲突 而失败时),因为文件路径不正确。这是它过去返回的错误:[SETUP error 101] error in opening file for component #2;文件名 = (ETHANE.FLD)。我通过指定完整路径解决了这个问题。

请注意,我还从 NIST 下载了其他代码,但它太复杂并且需要我没有安装的东西,所以我专注于你的代码(我什至将文件复制到相同的路径以获得尽可能接近您的环境)。

关于RefProp的个人看法:我不知道它到底是做什么的,我知道它是一种针对不同化学物质(大部分属于有机化学)的属性数据库,但在编程条款:

不确定 refrpop1.h 是如何诞生的:

  • RefProp 创建者提供
  • 由检查 dll 并找出函数签名的工具生成

如果是后者,那没关系,但如果是前者,那真的很糟糕,因为(我在这里只列举了最让我困扰的前 2 项):

  • 我找不到有关这些函数的任何文档。我不知道 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;
}

测试:

  • 我注意到访问冲突失败平均在 30 次运行时发生一次
  • 我还注意到,当 hf 没有完整路径时(因此 SETUPdll 返回错误 101),失败的频率更高;使用正确的路径我连续运行了 100 次(多次)而没有遇到它。我并不是说这是规则,这可能只是巧合。
  • 我将所有代码从 main 移到另一个 func 并在循环中从 main 调用它(1000 次迭代),也是多次,但失败并没有不要上来。

那么,最后一个问题:

我是否清楚地知道为什么程序因访问冲突(段错误)而失败?

答案是:

但是我检查了 REFPROP.DLL 依赖项,只有 2 个:KERNEL32.DLLUSER32.DLL(没有 < em>MSVCR*.DLL)。这意味着它已静态链接到 VC 运行时(或任何等效的 C 运行时)。另一方面,您的可执行文件也有自己的 VC 运行时(它如何链接到它并不重要)。

因此,您的可执行文件中有 2 个 C 运行时(一个在 exe 中,一个在 dll 中)。 C 运行时任务之一是内存管理:如何分配/释放内存(指针)(检查malloc/free 函数)。在某些情况下(如果 dll 代码和 exe 代码不“同步”),您最终可能会从一个运行时分配一个指针并从另一个运行时释放它,这可能会导致我们这里的行为。

关于c++ - 使用 refprop.dll 调用在访问冲突读取位置出现未处理的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32479500/

相关文章:

c++ - win32 C++ 上的按钮样式

visual-studio - 改进 Visual Studio 2017 中的 JSX 编辑

c++ - 如何为跨平台 C++ 开发设置 Visual Studio

delphi - 接口(interface) DLL 表单应用程序崩溃

c++ - 具有自动和结构化绑定(bind)的 Ranges V3 zip

c++ - 将 printf 语句转换为 cout?

c++ - GDB 如何知道它必须在指定的断点处中断?

c++ - Visual Studio 中的错误 : No symbols loaded for opencv_world310. dll

windows - Windows dll 可以检索自己的文件名吗?

c# - 类型 'Newtonsoft.Json.JsonConvert' 存在于 'Newtonsoft.Json.dll' 和 'NuGetApi2.dll' 中