都是从"稀奇古怪的问题"开始的,博主早年开始写C++程序时,最鄙视用全局变量的行为,对单件也很不屑,后来有段时间却突然觉得这些用很方便呢还,在到后来,猛然发觉那些个代码带来的坑真不止一二三啊,尤其是碰上嵌入式上的运行异常排查!
某天开始,还惯用上了用“指向自身的聚合”,这省了再单独定义一个类来维护对象集合的代码,但却带来了"新的问题"!下边是从某次异常调试中演变出来一个简化的小测例,当时主要用来测试为啥😩在了Qhash的代码行!
基于上边Qhash的测试,想再写个更通用的测例,结果"神奇的事情"发生了,搞不死啊直接。接下来,QtCreater竟默许了空指针调用,简直是反人类啊!且看代码:
/************全局对象 obj-a****************/ //.h class CObjectA { public: CObjectA(); private: static CObjectB ms_ObjectB; }; /************全局对象 obj-a****************/ //.cpp CObjectA g_ObjeA; //全局 CObjectB CObjectA::ms_ObjectB; //静态成员 CObjectA::CObjectA() { qDebug() << "Create A while " << "ms_ObjectB Addr:" << &ms_ObjectB; qDebug() << "ms-FindB1" << ms_ObjectB.FindB1(); qDebug() << "ms-FindB2" << ms_ObjectB.FindB2(); } /************ 静态成员 ms-obj-b ****************/ //.h class CObjectB { public: CObjectB(); public: int FindB1(); int FindB2(); private: CObjectC *m_pObjC; }; /************ 静态成员 ms-obj-b ****************/ //.cpp CObjectB::CObjectB() { qDebug() << "Create B"; m_pObjC = NULL; m_pObjC = new CObjectC(); } int CObjectB::FindB1() { return 0x0B; } int CObjectB::FindB2() { return m_pObjC->FindC(); } /************ 普通成员 ms-obj-c ****************/ //.h class CObjectC { public: CObjectC(); public: int FindC(); }; /************ 普通成员 ms-obj-c ****************/ //.cpp CObjectC::CObjectC() { qDebug() << "Create C"; } int CObjectC::FindC() { qDebug() << QString("Execute ObjectC(%1)->FindC()") .arg((int)this, 8, 16, QChar('0')); return 0x0C; }运算结果如下:
猜测 可能是编译运行环境的优化参数导致的,此处并未做深究。需要明确的时,我们不允许发生这种情况。 至于为什么static QHash的就死掉了,可能更 volatile 可能与其不可优化性有关—
应该尽量避免创建全局对象,减少单体对象的使用。
使用全局变量的危害 1、发生初始化异常时,难以排查问题位置。 2、main函数前的创建较多时,对于开机耗时无法有效测试。 3、在全局变量中进行字符串读写时,可能会发生乱码问题,因为此时main函数中setCode并未设置
普通成员变量是在所属构造函数执行前就已经初始化好的- 我们可以定义写简单类的成员对象-然后依次打印创建顺序…
