C++構造函數使用memset初始化可能導致的問題

今天在寫代碼的時候突然遇到一箇中斷問題,但是光看代碼根本發現不了錯誤,代碼大概類似於:

typedef struct MemsetTest
{
	int     year;
	map<int,string> m_map;

	MemsetTest()
	{
		memset(this , 0 , sizeof(MemsetTest));
	}
}MemsetTest;


int Main()
{
	MemsetTest tTest;
	tTest.year = 2020;
	tTest.m_map[5] = "5";
}

其中爲map添加值那一行會報錯。

遇到這個問題之後看代碼是在想不出問題在哪,然後我就把源代碼中MemsetTest的結構體給複製到了一個新的工程中測試,但是還是會爆錯,於是我試着刪除了MemsetTest的m_map變量,在測試是可以正常運行的;但是變得更迷惑了,map用了沒有一千也有八百次了,爲什麼這裏會死機?就繼續刪代碼一點點測試,最後刪到發現有memset與map同時存在就會出問題;在網上一搜索瞭解到問題果然出現在memset上:memset()函數將對象的所有內存都初始化爲0,這在初始化的類是一個POD類型(Plain Old Data)時是沒有問題的,因爲POD類型的二進制內容可以隨便複製、移動、重置而不會改變POD類型對象的值。ConfigSettings成員都是POD類型(int,char,float…),而且ConfigSettings類既不存在虛繼承也不存在虛函數,所以可以對ConfigSettings使用memset()函數進行初始化。但是因爲我在MemsetTest中加入了map類型的成員變量,就導致MemsetTest不再是一個POD類型結構,所以當使用memset()函數進行初始化時會對對象造成破壞,map底層是紅黑樹,其中必然包括各種指針,當使用memeset將對象所有內存初始化爲0的時候,map中的各種指針必然就變成了null_ptr,整個結構已經被完全破壞了,所以會後面對map進行操作的時候就會出現崩潰。

 

最後解決辦法

  1. 重新寫MemsetTest的構造函數,不再使用memset()函數初始化對象。
  2. 將成員變量map設置爲static類型,可以避免在memset()時被破壞.

另外以後一定要注意構造函數初始化儘量不要直接使用memset,因爲就算你寫的時候是一個POD結構,但隨着時間的流逝後續其他人維護就可能添加指針等,到時他如果不瞭解這個問題就又會困住他好久。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章