【问题标题】:Why is my destructor not being called?为什么我的析构函数没有被调用?
【发布时间】:2013-05-23 23:30:36
【问题描述】:

程序退出时没有调用我的析构函数。该对象是一个单身人士,也许我错过了什么?

这是头文件和cpp文件:

#ifndef MYSQLCONNECTOR_H
#define MYSQLCONNECTOR_H

/* Standard C++ headers */
#include <iostream>
#include <string>

/* MySQL Connector/C++ specific headers */
#include <driver.h>
#include <connection.h>
#include <statement.h>
#include <prepared_statement.h>
#include <resultset.h>
#include <metadata.h>
#include <resultset_metadata.h>
#include <exception.h>
#include <warning.h>

class MysqlConnector {
private:
    static bool instanceFlag;
    static MysqlConnector* mysqlConnector;

    MysqlConnector() {

    };
public:
    static sql::Driver *driver;
    static sql::Connection *conn;
    static MysqlConnector* getInstance();

    virtual ~MysqlConnector() {
        instanceFlag = false;
        conn->close();
        delete conn;
        std::cout << "called" << std::endl;
    };
private:

};

#endif  /* MYSQLCONNECTOR_H */

还有cpp文件

#include "MysqlConnector.h"

using namespace std;
using namespace sql;

bool MysqlConnector::instanceFlag = false;
MysqlConnector* MysqlConnector::mysqlConnector = NULL;

MysqlConnector* MysqlConnector::getInstance() {
    if (!instanceFlag) {
        mysqlConnector = new MysqlConnector();
        instanceFlag = true;

        try {
            driver = get_driver_instance();

            /* create a database connection using the Driver */
            conn = driver->connect("tcp://127.0.0.1:3306", "root", "root");

            /* turn off the autocommit */
            conn -> setAutoCommit(0);

            /* select appropriate database schema */
            conn -> setSchema("exchange");

        } catch (SQLException &e) {
            cout << "ERROR: SQLException in " << __FILE__;
            cout << " (" << __func__ << ") on line " << __LINE__ << endl;
            cout << "ERROR: " << e.what();
            cout << " (MySQL error code: " << e.getErrorCode();
            cout << ", SQLState: " << e.getSQLState() << ")" << endl;

            if (e.getErrorCode() == 1047) {
                cout << "\nYour server does not seem to support Prepared Statements at all. ";
                cout << "Perhaps MYSQL < 4.1?" << endl;
            }
        } catch (std::runtime_error &e) {
            cout << "ERROR: runtime_error in " << __FILE__;
            cout << " (" << __func__ << ") on line " << __LINE__ << endl;
            cout << "ERROR: " << e.what() << endl;
        }

        return mysqlConnector;
    } else {
        return mysqlConnector;
    }
}

【问题讨论】:

  • 你应该看看人们对单身人士的看法。
  • 他们说什么,我去看看,参考?

标签: c++ oop destructor


【解决方案1】:

您的析构函数没有被调用,因为没有人为使用new 创建的对象调用delete

mysqlConnector = new MysqlConnector(); // Where's the corresponding call to delete?

您可以考虑改用智能指针(如果您负担得起 C++11,我会建议 std::unique_ptr)。当智能指针本身被销毁时,它会自动在封装对象上调用delete

另一种可能性是根本不使用指针,并拥有MysqlConnector 类型的静态数据成员。然后getInstance() 可以返回对该对象的引用(而不是指针)。

【讨论】:

  • 如果程序退出,那么这些newd 对象会被破坏,对吗?还是只有它们占用的内存被操作系统回收?
  • @Koushik:不,除非有对 delete 的调用,否则它们不会被销毁。对delete 的调用可能不是显式的——就像使用智能指针等RAII 包装器时的情况一样,但它必须存在。如果它不存在,则内存泄漏(除非使用了一些花哨的模式,但 OP 的问题并不暗示)。然后,在进程终止时,由进程分配的内存被操作系统收回。
  • 所以在程序终止期间,如果没有明确删除,对象会处于无效状态,而其内存会以任何一种方式被回收?
  • 我尝试使用 auto_ptr,但我认为我做错了。有没有我可以去的地方的单身人士的例子?
  • @Koushik:该对象没有处于无效状态,它可以处于有效状态并且不会被销毁。但是是的,内存在进程终止后由操作系统回收。
【解决方案2】:
static MysqlConnector* mysqlConnector;

是指向类的指针。当您获得实例时,它只返回此指针。您需要在此静态指针上调用 delete 才能调用析构函数。

如果您继续对该指针调用 delete,请确保仅在程序终止时才这样做 - 因为下一次调用 getInstance() 将创建一个新对象。

编辑 - 刚刚发现了 instanceFlag,因此它不会创建新实例,但会返回一个 NULL 指针

这是有问题的,因为您可能希望 Singleton 是同一个对象,但当然创建它的新实例将意味着您的数据不会持久化(即使您正在访问单例)。

无论如何,操作系统都会回收内存,所以您最好公开连接关闭代码并自己调用它?

【讨论】:

    猜你喜欢
    • 2010-12-21
    • 1970-01-01
    • 2010-11-21
    • 1970-01-01
    • 1970-01-01
    • 2017-11-18
    • 2013-01-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多