【问题标题】:Access violation error in debug mode but application runs in release mode for a dll compiled in visual studio2015调试模式下的访问冲突错误,但应用程序在 Visual Studio2015 中编译的 dll 的发布模式下运行
【发布时间】:2022-01-14 11:16:54
【问题描述】:

我在 32 位模式下使用 Visual Studio 2015 编译一个 dll(VSDll),它调用另一个 dll 中编写的函数(MATLAB 函数由 MATLAB C++ 编译器导出为 dll)。然后由 .exe 文件调用此 VSDLL。现在,我可以成功地将代码编译成调试和发布 DLL。我还可以从 .exe 文件成功运行发布 dll。它运行没有任何问题。但是当我尝试在 Visual Studio 中以调试模式运行代码时,我收到以下错误Error message。 这个图有寄存器信息和出错的栈帧。Stack Frame and registers。还在这里附加了堆栈跟踪信息。 Stack trace.

这可能是一个愚蠢的错误,但我是 C++ 新手,对内存堆和堆栈没有很深入的了解。我尝试按照其他答案中的建议在调试模式下启用/禁用不同的设置,这些答案对其他人有用,但在我的情况下没有任何作用。我之前使用的是 Visual Studio 专业版,我可以在没有此错误的情况下进行调试。现在最近我不得不更改为 Visual Studio 社区版,从那时起,只有当我尝试在我的代码中设置断点并对其进行调试时,我才会遇到这个问题。这可能是问题吗?我注意到的另一件事是,我正在使用 Visual Studio 将各种 MATLAB 函数编译为 dll,并使用它们构建自定义 dll 以在 TRNExe 中运行。每个都在发布模式下工作正常,但在调试模式下,每次故障的相同 boost_log-vc110-mt-1_49.dll 和相同的内存寄存器 0x​​7e37a348。 谁能帮我解决这个错误?对于可能出现的问题,我很感激任何想法或建议。

请在此处查看警告消息。这可能是问题的根源吗?Warning message

我在下面制作了一个最小的可重现示例。它仍然是免费的代码行。另一个瓶颈是,我正在尝试在 Trnsys 和 MATLAB 之间进行联合仿真。 Trnsys 将其组件编写为类型 DLL(Fortran 或 C++),并且它具有此 dll 的结构。我正在尝试将 MATLAB 函数导出为 dll,在代码的所需部分以 Trnsys 类型调用它,并将其编译为 DLL 以在 Trnsys 仿真工作室中运行。因此,C++ 将 MATLAB dll 链接到 TRNSYS 内核库 TRNDll。作为一个最小的可重现示例,我不知道如何做到这一点。无论如何,我已经编译了 MATLAB 代码以添加两个数字并在 Type201.cpp(尊重 TRNSYS 结构)中调用它并将其编译到 DLL 中以在 TRNSYS studio 中运行。它在那里工作。但是当我尝试在调试模式下运行 Type201.cpp 时,我仍然在确切的堆栈帧和 boost_log-vc110-mt-1_49.dll 的寄存器处得到与以前完全相同的错误。

键入201.cpp代码如下

    extern "C" __declspec(dllexport) void TYPE201(void)
    {
        double a;
        double b;
        double Timestep, Time, StartTime, StopTime;
        int index, CurrentUnit, CurrentType;
   
        mxArray* x_ptr ;
        mxArray* y_ptr ;
        mxArray* z_ptr = NULL;
        double* output = NULL;
        //Get the Global Trnsys Simulation Variables
        Time = getSimulationTime();
        Timestep = getSimulationTimeStep();
        CurrentUnit = getCurrentUnit();
        CurrentType = getCurrentType();
        StartTime = getSimulationStartTime();
        StopTime = getSimulationStopTime();
        //Set the Version Number for This Type
        if (getIsVersionSigningTime())
        {
            int v = 17;
            setTypeVersion(&v);
            return;
        }
    
        //Do All of the Last Call Manipulations Here
        if (getIsLastCallofSimulation())
        {
            addlibTerminate();
            mclTerminateApplication();
            return;
        }
    
        //Perform Any "End of Timestep" Manipulations That May Be Required
        
    
        //Do All of the "Very First Call of the Simulation Manipulations" Here
        if (getIsFirstCallofSimulation())
        {
            //Tell the TRNSYS Engine How This Type Works
            int npar = 2;
            int nin = 2;
            int nder = 0;
            int nout = 1;
            int mode = 1;
            int staticStore = 0;
            int dynamicStore =1;
    
            setNumberofParameters(&npar);
            setNumberofInputs(&nin);
            setNumberofDerivatives(&nder);
            setNumberofOutputs(&nout);
            setIterationMode(&mode);
            setNumberStoredVariables(&staticStore, &dynamicStore);
    
            return;
        }
    
        //Do All of the "Start Time" Manipulations Here - There Are No Iterations at the Intial Time
        if (getIsStartTime())
        {
            
            index = 1; a = getInputValue(&index);
            index = 2; b = getInputValue(&index);
            
    
            if (!mclInitializeApplication(NULL, 0))
            {
                //fprintf(stderr, "Could not initialize the application.\n");
                exit(1);
            }
    
            if (!addlibInitialize())
            {
                //fprintf(stderr, "Could not initialize the library.\n");
                exit(1);
            }
            //Read in the Values of the Inputs from the Input File
    
            return;
    
        }
        if (getIsEndOfTimestep())
        {
    
            
            return;
        }
    
        //---------------------------------------------------------------------------------------------------------------------- -
        //ReRead the Parameters if Another Unit of This Type Has Been Called Last
    
    
    
        //Get the Current Inputs to the Model
        index = 1;
        a = getInputValue(&index);
        index = 2; 
        b = getInputValue(&index);
        int noutput = getNumberOfOutputs();
        
        //Create an mxArray to input into mlfAdd 
        x_ptr = mxCreateDoubleMatrix(1, 1, mxREAL);
        y_ptr = mxCreateDoubleMatrix(1, 1, mxREAL);
        memcpy(mxGetPr(x_ptr), &a, 1 * sizeof(double));
        memcpy(mxGetPr(y_ptr), &b, 1 * sizeof(double));
        
        mlfAdd(1, &z_ptr, y_ptr, x_ptr);
        output = mxGetPr(z_ptr);
        index = 1;
        setOutputValue(&index, output);
        
        return;
    
    }

那么这就是两个数字相加的 MATLAB 函数。

    function [s] = add(a,b)
         s = a+b;
    end

我通过命令行将它编译成 dll 使用

mcc -B csharedlib:addlib add.m

【问题讨论】:

  • “调试模式下的访问冲突错误”和“在发布中运行”都是未定义行为的症状,潜伏在代码中的某个地方。 UB 就是这样偷偷摸摸的。
  • 如果您在编译代码时打开所有警告消息的所有选项,您是否会从编译器收到任何警告消息?不幸的是,没有minimal reproducible example,Stackoverflow 上的任何人都不太可能告诉你更多信息。错误消息、寄存器转储和堆栈跟踪本身,没有minimal reproducible example,没有有意义的内容。
  • 感谢您的评论。有什么提示可以追踪问题吗?我无法在调试模式下逐行调试代码。没有这个,我不知道在哪里寻找问题。
  • 如前所述,始终建议将编译器的警告级别调高。编译时是否看到任何警告?
  • 我已编辑问题以添加警告消息。这有什么线索吗?我认为这些警告是无害的。我现在就修。

标签: c++ matlab visual-studio-2015 32-bit matlab-compiler


【解决方案1】:

这可能是因为某些 std 类和 boost 类在发布和调试版本中具有不同的布局。在调试版本中,通过宏插入额外的成员,以实现更好的调试体验,如迭代器调试等。因此,正如 Microsoft 所记录的,混合链接到不同 c++ 运行时的代码是未定义的行为。 matlab dll 是在发布模式下构建的,并链接到 c++ 发布运行时,因此它不应该被链接到调试库的代码使用!

【讨论】:

  • 感谢您的回复。您的回答很有道理,但我不明白为什么我仍然可以在 Visual Studio Code 专业版中运行它。
  • @AmithaMayyaP 如果您觉得答案有用,请将其标记为正确答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-19
相关资源
最近更新 更多