C 由於結構體對齊問題造成的程式崩潰

2021-09-29 20:48:26 字數 1193 閱讀 9947

在專案中,遇到乙個由於結構體對齊問題造成程式崩潰問題,測試了半天,終於復現了出來。

首先定義乙個標頭檔案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 因為 成員對齊有乙個重要的條件,即每個成員按自己的方式對齊.其對齊的規則是,每個成員按其型別的對齊引數 通常是這個型別的大小 和指定對齊引數 這...