Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/visual-studio-2010/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 避免vc内存崩溃的内联类构造函数_C++_Visual Studio 2010 - Fatal编程技术网

C++ 避免vc内存崩溃的内联类构造函数

C++ 避免vc内存崩溃的内联类构造函数,c++,visual-studio-2010,C++,Visual Studio 2010,C++类构造函数可以内联,也可以不内联。然而,我发现了一种奇怪的情况,即只有内联类构造函数才能避免VisualStudio内存崩溃。示例如下: int main() { TestimagePtr my_img(new Testimage()); return 0; } dll.h 可执行程序将调用dll库,并静态链接运行库。我遇到的问题是,在运行可执行程序时,会出现以下错误消息: 但是,当dll中的类构造函数内联时,如下代码所示: class _declspec(dllexp

C++类构造函数可以内联,也可以不内联。然而,我发现了一种奇怪的情况,即只有内联类构造函数才能避免VisualStudio内存崩溃。示例如下:

int main()
{
    TestimagePtr my_img(new Testimage());
    return 0;
}
dll.h

可执行程序将调用dll库,并静态链接运行库。我遇到的问题是,在运行可执行程序时,会出现以下错误消息:

但是,当dll中的类构造函数内联时,如下代码所示:

class _declspec(dllexport) Image 
{
    public:
        Image();
        virtual ~Image();
};

class _declspec(dllexport) Testimage:public Image 
{
public:
    Testimage()
    {
    }

    virtual ~Testimage();
};
崩溃将消失。有人能解释一下背后的原因吗?谢谢顺便说一下,我正在使用VC2010

编辑:以下情况也会触发相同的崩溃

情景1

int main()
{
    //TestimagePtr my_img(new Testimage());
    Testimage *p_img;
    p_img = new Testimage();
    delete p_img;
    return 0;
}

我试图在VC2010中重现您的问题,但它没有崩溃。它是否与构造函数内联工作。你的问题可能不在于你在这里写了什么

您的项目太难打开,因为它无法将其文件路径设置为绝对路径,这可能是因为使用CMake生成的。(因此编译器找不到这些文件)

我在代码中看到的问题是,您使用直接编写的_declspec(dllexport)声明导出的类

您应该有一个#Define来执行此操作,从exe编译读取时,该值应为_declspec(dllimport)。也许问题就在于此

静态链接到C++运行库(多线程调试(/MTD)

在VS2012之前的Visual Studio版本中,这是一个非常有问题的场景。问题是您的进程中加载了多个CRT版本。一个版本由EXE使用,另一个版本由DLL使用。这可能会导致许多微妙的问题,而不是像此崩溃这样微妙的问题

CRT具有全局状态,当全局状态由CRT的一个副本更新并由另一个副本读回时,errno和strtok()之类的东西无法正常工作。与崩溃相关的是,一个隐藏的全局状态变量是CRT用于分配内存的堆。malloc()和::operator new等函数使用该堆

当对象由CRT的一个副本分配并由另一个副本释放时,就会出现错误or::operator delete属于错误的堆。接下来会发生什么取决于您的操作系统。XP中存在静默内存泄漏。在Vista及更高版本中,您的程序运行时启用了内存管理器的调试版本。当您将调试器连接到进程时,会触发一个断点,以告诉您指针有问题r、 屏幕截图中的对话框就是结果。我不太清楚内联构造函数会有什么不同,但最根本的问题是代码调用未定义的行为。这有一个生成随机结果的诀窍

有两种方法可以解决此问题。第一种是简单的方法,只需使用/MD compile选项构建EXE和DLL项目。这将选择CRT的DLL版本。它现在由两个模块共享,并且您的进程中只有一个CRT副本。因此不再有问题一个模块分配内存,另一个模块释放内存,使用相同的堆

这可以很好地解决您的问题,但在以后仍然会成为一个问题。DLL往往有自己的生命,并且可能有一天会被另一个使用不同版本CRT构建的EXE使用。CRT现在将不再共享,因为它们将使用不同版本的DLL,调用与您看到的完全相同的故障模式今天是星期五

<> P>唯一保证的方法是仔细设计DLL接口,确保DLL不会分配客户端代码需要释放的内存。这需要放弃大量的C++软件。例如,你永远不能编写一个返回C++对象的函数,比如STD::String。而且,您永远不能允许异常跨越模块边界。您基本上只能使用C风格的接口。请注意COM如何通过使用基于接口的编程技术和类工厂加引用计数来解决内存管理问题,从而解决此问题

VS2012有一个针对这个问题的对策,它有一个从默认进程堆分配的CRT版本。这解决了这个特定问题,而不是其他运行时函数全局状态问题的解决方法。并且添加了一些新问题,一个使用/MT编译的DLL被卸载,不会释放其所有例如,位置现在会导致不可插拔的泄漏


这是C++中的一个难看的问题,语言根本忽略了一个ABI规范,它解决了这样的问题。模块的概念完全没有语言规范。在今天工作但尚未完成。不简单,它通过指定vi来用java和.NET语言等其他语言来解决。RATE机器,提供内存管理是集中的运行环境,不是激发C++程序员的运行环境。

尝试动态链接CRT和/MCAN,你可以临时改变它并检查它是否有效?还有,你能告诉我为什么你必须静态链接它吗?我很好奇。我试着重现这种情况。与此同时,你为什么认为/Mt更稳定?正如你所看到的那样。通过静态链接CRT,你显式地创建了多个堆。一个在dll中,另一个在主机中。因此,在dll中分配内存并在主机中删除它会杀死你的应用程序。你所谓的内联实际上不是内联。W当您在头中实现并包含该ctor时,您将该ctor引入主机堆,这就是为什么它在本例中不会崩溃case@Samuel构造函数是否为inlin并不重要
class _declspec(dllexport) Image 
{
    public:
        Image();
        virtual ~Image();
};

class _declspec(dllexport) Testimage:public Image 
{
public:
    Testimage()
    {
    }

    virtual ~Testimage();
};
int main()
{
    //TestimagePtr my_img(new Testimage());
    Testimage *p_img;
    p_img = new Testimage();
    delete p_img;
    return 0;
}