综合经验:IO读写错误必然导致程序崩溃

仿佛是忽然间产生的问题,每次程序退出时候,必然崩溃,花了整整一天才找到原因,就是对数据库的IO读写错误。主要是因为析构函数调用了Disconnect函数,内容如下:

void SFTPTool::Disconnect()
{
    if (!m_valided) 
        IsCompteValide();
    if (!m_valided) {
        return;
    }
    QString strModule = "soft";
    if (!m_taskname.isEmpty()) strModule = m_taskname;
    m_sftp->Disconnect();
    // super exp 使用登录框时,没有初始化m_lite实例,此时插入日志,程序必然崩溃!
    if (SystemGlobal::m_lite) // hang exp 这样可以解决登录框的问题,但无法解决正常退出的问题(估计是全局远程连接造成的问题)
        SystemGlobal::m_lite->InsertLog("task", strModule, "disconnect", tr("disconnect by soft"));
}

崩溃的原因有两种情况:

1. 使用登录框的时候,因为System::m_lite在主界面MainWidget的构造函数中实例化,所以必然失败。这个问题通过加上if (SystemGlobal::m_lite)可以解决。

2. 软件主界面退出时,仍然出错,还是因为红色的句子。我想可能是因为有个g_sftp实例晚于主界面被析构(因为是静态实例),此时主界面都没有了,因此数据库实例也被析构了,然后在内存中把全局实例析构,就发生了错误。

综合以前的经验,教训总结:碰到IO错误,程序必然崩溃。碰到内存错误,有时候崩溃有时候不崩溃,有可能会产生误用数据而不一定崩溃。除非读写OS保护区域的内存,才会必然崩溃。使用野指针都不一定崩溃。

 

MainWidget::~MainWidget()
{
    SystemGlobal::m_lite->InsertLog("app", "soft", "exit");
    // exp 使用全局锁居然会出错 fixme 各对象的析构顺序是怎样的?
    if (SystemGlobal::m_lite) {
        delete SystemGlobal::m_lite; // OO 删除内存对象,不是删除日志数据库文件。这样万无一失,可随时停止日志
        SystemGlobal::m_lite = NULL; // Archi 即使在主界面中析构,也仍然要把指针赋予空值,因为全局内存对象析构比主界面还晚,因此仍会出错
    }
    if (SystemGlobal::m_index) {
        delete SystemGlobal::m_index;
        SystemGlobal::m_index = NULL;
    }
}

 

经试验,在主界面中把指针赋予空值也可解决问题。

 

你可能感兴趣的:(IO)