当C ++ DLL程序退出时:运行时检查失败#2

时间:2012-04-29 06:13:34

标签: c++ visual-studio-2010 dll

我在使用C ++编写的DLL时遇到问题。有一些非常奇怪的行为正在发生,我自己无法解决。

很难准确描述发生了什么,但我会尽我所能。基本上我在我的DLL中有一个类,它有一个私有属性和一个公共构造函数。 当我初始化此类然后退出程序时,我收到错误。

  

“运行时检查失败#2 - 围绕变量'test'进行堆栈   损坏“

我在这里 2个项目

  1. 名为“ testdll ”的DLL。
  2. 控制台测试程序名为“测试”。
  3. 我把这个错误归结为最简单的可重复形式,试图缩小可能的原因,下面你会找到我的代码。

    项目“testdll”,文件testdll.h:

    #include <string>
    
    class testdll
    {
    public:
    __declspec(dllexport) testdll(); // Empty but same error if prams are used.
    
    private:
    std::string _var;
    };
    

    项目“testdll”,文件testdll.cpp:

    #include "testdll.h"
    
    testdll::testdll()
    {
    }
    

    项目“test”,文件testdll.h:

    #include <string>
    
    class testdll
    {
    public:
        __declspec(dllimport) testdll();
    };
    

    项目“测试”,文件stdafx.h:

    #pragma once
    
    #include "targetver.h"
    
    #include <tchar.h>
    

    项目“测试”,文件test.cpp:

    #include "stdafx.h"
    #include "testdll.h"
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    testdll test;
    
    return 0;
    }
    

    如果您愿意,我可以使用您选择的存档格式向您发送 Visual C ++ 2010 解决方案文件。请帮忙!我不知道发生了什么。

    可选信息: 语言(或软件):C ++

    已经尝试过: 删除构造函数定义,它既可以使用但不是可用的解决方案,也不能解释问题。同时使我的所有私有属性成为指针,但我不应该这样做。

2 个答案:

答案 0 :(得分:1)

您正在使用两个头文件,它们不会声明同一个类。一个有std :: string成员,另一个没有。这非常非常糟糕,编译器没有为堆栈帧上的对象保留足够的空间。这是运行时错误告诉你的。非常好的功能btw,这种错误非常难以诊断。

你可能已经进入了这个pickle,因为你只将__declspec(dllexport)应用于构造函数而不是整个类。您需要编写头文件,以便它可以被您的dll项目用于您的exe项目。这应该是这样的:

#undef DLLEXPORT
#ifdef BUILDING_MYDLL
#  define DLLEXPORT __declspec(dllexport)
#else
#  define DLLEXPORT __declspec(dllimport)
#endif

class DLLEXPORT testdll
{
public:
    testdll();
private:
    std::string _var;
};

右键单击DLL项目,属性,C / C ++,预处理器,预处理器定义。附加BUILDING_MYDLL

删除exe项目目录中的testdll.h文件。设置C / C ++,General,Additional Include Directories设置,以便编译器可以在testdll项目目录中找到标题(如.. \ testdll)

答案 1 :(得分:0)

从DLL中导出类和类成员非常非常脆弱,正如您刚刚发现的那样。如果库和客户端都没有使用完全相同的类布局,这取决于所有类型的编译器设置,那么事情就会非常糟糕。

在您的情况下,您可能在std::string内使用了不兼容的class testdll版本。也许一个编译用于调试,一个用于发布。或者一个是使用静态运行时库,另一个是使用DLL运行时。谁能说?

无论如何,只要从DLL导出C ++功能,就可以锁定自己的编译器版本和设置。这是一场维护噩梦。

使用仅限v-table的基类或C兼容的包装函数。