關(guān)于C++中由于字節(jié)對齊引起內(nèi)存問題定位分析
最近遇到了一個(gè)奇怪的問題,在創(chuàng)建對象時(shí)程序異常退出,具體地,在構(gòu)造函數(shù)中訪問類中最后一個(gè)成員變量時(shí),程序異常退出。
問題定位
查看代碼,發(fā)現(xiàn)該類中有一個(gè)結(jié)構(gòu)體數(shù)組,該結(jié)構(gòu)體在類的外面聲明,用 #pragma pack(push,1) 設(shè)置了一字節(jié)對齊方式,而類不在這個(gè)作用范圍內(nèi),所以是按照默認(rèn)字節(jié)對齊方式的。懷疑該問題是因?yàn)?,類的字?jié)對齊方式和類中的結(jié)構(gòu)體字節(jié)方式不同引起的。但這從理論方面解釋不通。
繼續(xù)定位,在創(chuàng)建對象之前用sizeof打印類的大小,再在類的構(gòu)造函數(shù)中打印類的大小。發(fā)現(xiàn)這兩個(gè)大小居然不同。這證實(shí)了的確與字節(jié)對齊有關(guān),創(chuàng)建對象之前和在構(gòu)造函數(shù)中,兩邊選擇的字節(jié)對齊方式不同,導(dǎo)致計(jì)算類的大小不同。
但是為什么這兩個(gè)地方的字節(jié)對齊方式不同呢?
當(dāng)把該類也使用 #pragma pack(push,1) 設(shè)置字節(jié)對齊方式之后,類的大小又變得相同了。大膽猜測,由于 #pragma pack(push, 1) 是一種棧的結(jié)構(gòu),可能有某個(gè)文件中,設(shè)置了字節(jié)對齊方式之后,沒有用 #pragma pack(pop) 恢復(fù)。
查找全局文件,的確找到了一個(gè)文件存在這樣的問題,當(dāng)把 #pragma pack(pop) 后加上后,問題解決。
問題模型
我將這個(gè)問題簡化成下面這樣,可以幫助大家更好地理解。
CA.h,CA類的聲明,模擬只push,沒pop的文件
#ifndef CA_H
#define CA_H
#include <iostream>
using namespace std;
#pragma pack(push, 1)
class CA {
int a;
char b;
};
#endif
CB.h,CB類的聲明。St結(jié)構(gòu)體設(shè)置一字節(jié)對齊方式,CB類使用默認(rèn)字節(jié)對齊方式。
#ifndef CB_H
#define CB_H
#include <iostream>
using namespace std;
#pragma pack(push,1)
struct St {
int a1;
int a2;
int a3;
char a4;
char a5;
};
#pragma pack(pop)
class CB {
public:
CB();
int a1;
int a2;
int a3;
char a4;
char a5;
St a6[10];
bool a7;
};
#endif
CB.cpp,CB類的實(shí)現(xiàn)。
#include "CB.h"
#include <iostream>
using namespace std;
CB::CB()
{
cout << "constructor: sizeof(CB) = ";
cout << sizeof(CB) << endl;
}
main.cpp,用于創(chuàng)建CB對象
#include "CA.h"
#include "CB.h"
#include <iostream>
using namespace std;
int main()
{
cout << "main: sizeof(CB) = ";
cout << sizeof(CB) << endl;
CB *pCB = new CB;
}
編譯上述文件并執(zhí)行,可以得到下面的結(jié)果:
main: sizeof(CB) = 155
constructor: sizeof(CB) = 156
可以看到,兩處計(jì)算的類的大小是不同的。在main函數(shù)里,分配了155字節(jié)的空間,而在構(gòu)造函數(shù)中卻認(rèn)為有156字節(jié)的空間,當(dāng)訪問最后一字節(jié)時(shí),程序出現(xiàn)了踩內(nèi)存。
問題分析
為什么main.cpp和CB.cpp認(rèn)為CB的字節(jié)對齊方式不同呢?
這主要還是因?yàn)閙ain.cpp包含了CA.h,CA.h在main.cpp中展開,CB.h也展開,CA.h中設(shè)置的一字節(jié)對齊方式,影響到了CB類的聲明,當(dāng)編譯main.cpp時(shí),CB使用一字節(jié)對齊方式。
而CB.h沒有包含CA.h,當(dāng)編譯CB.cpp時(shí),并沒有受到CA.h的影響,CB使用默認(rèn)字節(jié)對齊方式。
以上就是關(guān)于C++中由于字節(jié)對齊引起內(nèi)存問題定位分析的詳細(xì)內(nèi)容,更多關(guān)于c++字節(jié)對齊內(nèi)存問題的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C語言system 自動(dòng)關(guān)機(jī)函數(shù)代碼
這篇文章主要介紹了C語言system 自動(dòng)關(guān)機(jī)函數(shù)代碼,需要的朋友可以參考下2016-04-04
C++中關(guān)于constexpr函數(shù)使用及說明
這篇文章主要介紹了C++中關(guān)于constexpr函數(shù)使用及說明,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11
Pipes實(shí)現(xiàn)LeetCode(194.轉(zhuǎn)置文件)
這篇文章主要介紹了Pipes實(shí)現(xiàn)LeetCode(194.轉(zhuǎn)置文件),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08
C語言實(shí)現(xiàn)簡單的圖書管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)簡單的圖書管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-03-03

