全域性變數誤用導致單例模式中的多次銷燬例項產生coredump
阿新 • • 發佈:2019-01-01
最近遇到一個問題,產生了coredump, 用gdb看也沒看出真正原因,合作方同事提醒才看出來。
模擬了一下出錯場景,程式碼如下:
class Person{ private: int *m_data; static Person *pInstance; public: Person(){ printf("Person\n"); m_data = new int[60]; printf("Person done\n"); } ~Person(){ printf("~Person\n"); if(m_data){ delete m_data; m_data = NULL; } printf("~Person done\n"); } static Person* getInstance(){ if(NULL == pInstance){ pInstance = new Person(); } return pInstance; } static void destroyInstance(){ if(pInstance){ delete pInstance; pInstance = NULL; } } } Person* Person::pInstance = NULL; class Person *gpPersonInstance = NULL; void init(){ gpPersonInstance = Person::getInstance(); } void finilize(){ if(gpPersonInstance){ delete gpPersonInstance; gpPersonInstance = NULL; } //Person::destroyInstance(); } int main(void){ init(); printf("gpPersonInstance addr: %p\n", gpPersonInstance); finilize(); printf("pInstance addr: %p\n", Person::getInstance()); init(); finilize(); }
在第一次init() finilize(); 正常,把單例例項銷燬了,全域性製作也gpPersonInstance = NULL; 但pInstance 沒有設定為NULL。
當第二次init()時,由於pInstance不為NULL,所以直接把之前的值賦值給gpPersonInstance 了, 再次finilize() 就會delete一個不是自己new的物件的地址,產生coredump。
在finilize()函式中把
if(gpPersonInstance){ delete gpPersonInstance; gpPersonInstance = NULL; }
用
Person::destroyInstance(); 代替就沒有問題