在專案中,遇到乙個由於結構體對齊問題造成程式崩潰問題,測試了半天,終於復現了出來。
首先定義乙個標頭檔案test.h:
class test
;
然後再建立test.cpp檔案完成建構函式:
test::test()
可以看出這裡建構函式什麼都沒乾,但是它必須要,否則不會造成崩潰,這主要與下面的main.cpp有關:
#pragma pack(1)
#include "test.h"
int main()
正常來說,應該輸出為「 」;如果沒有定義建構函式,或者建構函式在標頭檔案中實現,是正常輸出為「 」;但是在cpp中實現了建構函式,它最後報錯read access violation at 0x0;
通過除錯,發現類成員name提示無法訪問。
查了半天資料,發現是與結構體對齊和成員string有關係;
因為在主函式開頭定義了結構體對齊方式為1個位元組,那麼test.h裡的結構體也就以乙個位元組的形式對齊;但是test.cpp建構函式沒有,仍然以預設8個位元組對齊;
在test.cpp列印test的位元組數和在main.cpp裡面列印的位元組數測試是不一樣,乙個為48,乙個為42(在我的平台上string型別位元組數為40);
因為c++通過建構函式完成物件的建立,如以1表示第乙個位址,那麼在main函式中物件test的name首位址為3,而new出來的物件首位址為9,而string本身是乙個類,裡面包含指標變數,類似於:
class string
c++在以指標變數賦值的時候,要特別注意記憶體問題(這裡具體我也是理解得還不夠深)
當然#pragma pack(1)在test.h中定義本例不會出現問題,因為test.cpp中包含了test.h; 但是在複雜程式中,如果不恢復預設方式,可能會造成其他模組 的結構體錯誤,因此注意在定義結構體對齊方式時,要特別注意對齊方式的恢復;
#pragma pack(push)//壓棧當前對齊方式
#pragma pack(1)
...#pragma pack(pop)//恢復以前的對齊方式
/*****************/
#pragma pack()//恢復預設對齊方式
C語言結構體對齊問題
結構體對齊規則 預設對齊方式,按結構體的成員中 size 最大的成員對齊。拋開成員size來說,一般情況下32位機器預設4位元組對齊,64位機器預設8位元組對齊。另外可以使用偽指令 pragma pack n 修改預設的位元組對齊。1.使用偽指令 pragma pack n 編譯器將按照 n 個位元...
C語言結構體對齊 記憶體對齊問題
c語言結構體對齊也是老生常談的話題了。基本上是面試題的必考題。內容雖然很基礎,但一不小心就會弄錯。寫出乙個struct,然後sizeof,你會不會經常對結果感到奇怪?sizeof的結果往往都比你宣告的變數總長度要大,這是怎麼回事呢?有人給對齊原則做過總結,具體在 看到現在已記不起來,這裡引用一下前人...
結構體對齊問題
1,比如 structa structb sizeof a 6,sizeof b 8,為什麼?注 sizeof short 2,sizeof long 4 因為 成員對齊有乙個重要的條件,即每個成員按自己的方式對齊.其對齊的規則是,每個成員按其型別的對齊引數 通常是這個型別的大小 和指定對齊引數 這...