根据链接顺序,不调用C ++析构函数 [英] C++ destructor not being called, depending on the linking order

查看:91
本文介绍了根据链接顺序,不调用C ++析构函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在检查内存泄漏后,我在应用程序中遇到了这个问题,发现我的某些类根本没有被销毁。

I ran across this issue in my application after checking it for memory leaks, and discovered that some of my classes are not being destroyed at all.

下面的代码分为3个文件,应该实现称为 pimpl 。预期的情况是同时让 Cimpl 构造函数和析构函数打印其消息。但是,这不是我用g ++得到的。在我的应用程序中,只有构造函数被调用。

The code below is split into 3 files, it is supposed to implement a pattern called pimpl. The expected scenario is to have both Cimpl constructor and destructor print their messages. However, that's not what I get with g++. In my application, only constructor got called.

classes.h:

classes.h:

#include <memory>

class Cimpl;

class Cpimpl {
    std::auto_ptr<Cimpl> impl;
public:
    Cpimpl();
};

classes.cpp:

classes.cpp:

#include "classes.h"
#include <stdio.h>

class Cimpl {
public:
    Cimpl() {
        printf("Cimpl::Cimpl()\n");
    }
    ~Cimpl() {
        printf("Cimpl::~Cimpl()\n");
    }
};    

Cpimpl::Cpimpl() {
    this->impl.reset(new Cimpl);
}

main.cpp:

#include "classes.h"

int main() {
    Cpimpl c;
    return 0;
}

这就是我能够进一步发现的东西:

Here is what I was able to discover further:

g++ -Wall -c main.cpp
g++ -Wall -c classes.cpp
g++ -Wall main.o classes.o -o app_bug
g++ -Wall classes.o main.o -o app_ok

它好像在两种可能情况之一中调用了析构函数,它取决于链接顺序。使用app_ok,我可以得到正确的场景,而app_bug的行为与我的应用程序完全一样。

It looks like the destructor is being called in one of two possible cases, and it depends on the linking order. With app_ok I was able to get the correct scenario, while app_bug behaved exactly like my application.

在这种情况下,我是否缺少任何智慧?
感谢您提前提出任何建议!

Is there any bit of wisdom I am missing in this situation? Thanks for any suggestion in advance!

推荐答案

pimpl习惯用法的目标是不必公开定义头文件中实现类的名称。但是所有标准智能指针都要求定义其模板参数,以便在声明时可见 才能正常工作。

The goal of the pimpl idiom is to not have to expose a definition of the implementation class in the header file. But all the standard smart pointers require a definition of their template parameter to be visible at the point of declaration in order to work correctly.

意味着这是您真正想使用 new delete 和裸露指针的罕见情况之一。 (如果我错了,并且有一个 standard 智能指针可以用于pimpl,请让我知道。)

That means this is one of the rare occasions where you actually want to use new, delete, and a bare pointer. (If I'm wrong about this and there's a standard smart pointer that can be used for pimpl, someone please let me know.)

struct Cimpl;

struct Cpimpl
{
    Cpimpl();
    ~Cpimpl();

    // other public methods here

private:
    Cimpl *ptr;

    // Cpimpl must be uncopyable or else make these copy the Cimpl
    Cpimpl(const Cpimpl&);
    Cpimpl& operator=(const Cpimpl&);
};



classes.cpp



classes.cpp

#include <stdio.h>

struct Cimpl
{
    Cimpl()
    {
        puts("Cimpl::Cimpl()");
    }
    ~Cimpl()
    {
        puts("Cimpl::~Cimpl()");
    }

    // etc
};

Cpimpl::Cpimpl() : ptr(new Cimpl) {}
Cpimpl::~Cpimpl() { delete ptr; }

// etc

这篇关于根据链接顺序,不调用C ++析构函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆