[心得] 在 struct 中的 vector 存取異常
很久沒有寫心得了,這個問題花了我整整兩天的時間才解決,所以值得分享一下。首先我們看以下的定義
應該沒甚麼問題,除了條件式的組譯:如果有定義 BOOST 的話,就多一個 bBoost 的欄位
在我的 Solution 中有 ProjectA 和 ProjectB,其中 ProjectA 會產生 Profile 的物件,並以 Call by address 的方式傳給 Project B 中做後續的資料處理與回傳。
而問題出在 ProjectB 中只要對 OffsetVector 做寫入就會產生記憶體存取異常。我找過幾個方向:
所以結論是:
2016/8/4 續集
下列這段程式碼會產生 Memory leak
為甚麼呢?不過是利用 memset 初始化利用 new 建立的 struct,應該也沒問題才對啊!
原來還是 struct 中的 vector 出問題了,當你利用 new 建立 struct 時,裡面的 vector 實際上也會配置自己的 memory 空間,以便存放後續加入 vector 中的元素。當你用 memset 把所有 struct 中的元素清為 0 時,等於沒有把 vector 配置的 memory 釋放掉,就直接把 vector 清為 0。所以當程式結束時,就產生 Memory leak 了
因此,下次 struct 中有 STL 的容器時,千萬不要再用 memset 初始化了
typedef struct _Profile
{
INT nFormat;
BOOL bFanMode;
ULONG ulFanSpeed;
#ifdef BOOST
BOOL bBoost;
#endif
INT nOCMode;
vector<INT> OffsetVector;
} Profile, *PProfile;
應該沒甚麼問題,除了條件式的組譯:如果有定義 BOOST 的話,就多一個 bBoost 的欄位
在我的 Solution 中有 ProjectA 和 ProjectB,其中 ProjectA 會產生 Profile 的物件,並以 Call by address 的方式傳給 Project B 中做後續的資料處理與回傳。
而問題出在 ProjectB 中只要對 OffsetVector 做寫入就會產生記憶體存取異常。我找過幾個方向:
- 因為 vector 會動態配置記憶體來存取資料,所以初期一直朝這個方向找答案,是否在傳遞的過程中,vector 所指到的記憶體已經改變了?所以才造成異常。但相同的動作在 ProjectA 做卻完全沒問題
- struct alignment 的問題,是否兩個 Project 的配置不一樣,造成相同的欄位卻存取到不同的位址?因此我用 sizeof() 取得兩個這數所佔空間的大小,還真的不一樣,而且 OffsetVector 是指向 struct 中不同的 offset。但我查 Project alignment 的設定,一樣都是預設值
所以結論是:
- 以後不要在 struct 中設定條件式組譯,避免又發生同樣的問題。
- 而在程式碼中的條件式組譯,請定義在 Project Property | C/C++ | Preprocessor 的 Preprocessor Definitions 中,否則寫在程式碼中,有可能造成部份程式碼因為沒有 include 到定義的檔案而不正確
2016/8/4 續集
下列這段程式碼會產生 Memory leak
PProfile pProfile = new Profile;
memset(pProfile, 0, sizeof(Profile));
delete pProfile;
為甚麼呢?不過是利用 memset 初始化利用 new 建立的 struct,應該也沒問題才對啊!
原來還是 struct 中的 vector 出問題了,當你利用 new 建立 struct 時,裡面的 vector 實際上也會配置自己的 memory 空間,以便存放後續加入 vector 中的元素。當你用 memset 把所有 struct 中的元素清為 0 時,等於沒有把 vector 配置的 memory 釋放掉,就直接把 vector 清為 0。所以當程式結束時,就產生 Memory leak 了
因此,下次 struct 中有 STL 的容器時,千萬不要再用 memset 初始化了
留言