对齐方式有那些_字节对齐不慎引发的挂死问题
前言
之前程序是32位的,切到64位之后,一些隱藏的問題就暴露了。這不,一個(gè)由字節(jié)對齊導(dǎo)致的掛死問題就出來了。
字節(jié)對齊和64位
關(guān)于字節(jié)對齊,可參考《理一理字節(jié)對齊的那些事》,而之前也分享過另一個(gè)切64位之后出現(xiàn)的問題,有興趣的可以查看《記64位地址截?cái)嘁l(fā)的掛死問題》。
本文背景
本文出現(xiàn)的場景是,系統(tǒng)需要解析JSON文件,但是出現(xiàn)部分功能解析正常,部分掛死,并且32位程序正常,而64位程序掛死。鑒于原系統(tǒng)比較復(fù)雜,本文將會簡化其過程,來看看到底是什么導(dǎo)致了掛死。
本文示例代碼主要引自《一個(gè)超輕量級的JSON解析器》。
簡化后示例代碼
//來源:公眾號【編程珠璣】 //https://www.yanbinghu.com #include<stdio.h> #include<stdlib.h> #include<sys/stat.h> #include<string.h> #pragma pack(1) #include"cJSON.h" #pragma pack()/*省略部分代碼,完整代碼可查看附錄部分*/ int main(void) {char *filename = "./test.json";cJSON *pJson = NULL;cJSON *pTemp = NULL;pJson = prepare_parse_json(filename);if(NULL == pJson){printf("parse json failedn");return -1;}/*獲取name值*/pTemp = cJSON_GetObjectItem(pJson,"name");printf("name is %sn",pTemp->valuestring);/*獲取site值*/pTemp = cJSON_GetObjectItem(pJson,"site");printf("site is %sn",pTemp->valuestring);/*獲取age值*/pTemp = cJSON_GetObjectItem(pJson,"age");printf("age is %dn",pTemp->valueint);/*記得釋放相關(guān)內(nèi)存*/cJSON_Delete(pJson);pJson = NULL;return 0; }編譯運(yùn)行結(jié)果:
$ gcc -L. -o parseJson parseJson.c -lcjson $ ./parseJson Segmentation fault (core dumped)在實(shí)際中我們通過GDB觀察發(fā)現(xiàn),在解析JSON內(nèi)部查看JSON數(shù)據(jù)是完好的,但是調(diào)用完解析JSON之后,再去訪問使用就不對了,并且我們發(fā)現(xiàn),在不同的功能模塊中,調(diào)用結(jié)果不一樣,大部分模塊調(diào)用并沒有任何問題,而只有某個(gè)功能模塊調(diào)用出現(xiàn)問題。
真相
到底是什么導(dǎo)致的呢?
問題的根源在于下面這幾行代碼:
另外補(bǔ)充,cJSON結(jié)構(gòu)體如下:
typedef struct cJSON { //cJSON結(jié)構(gòu)體struct cJSON*next,*prev; /*后驅(qū)節(jié)點(diǎn)和前驅(qū)節(jié)點(diǎn)*/struct cJSON *child; /*孩子節(jié)點(diǎn)*/int type; /* 鍵的類型*/char *valuestring; /*字符串值*/int valueint; /* 整數(shù)值*/double valuedouble; /* 浮點(diǎn)數(shù)值*/char *string; /* 鍵的名字*/ } cJSON;#pragma指令說明了按一字節(jié)對齊,而cJSON的頭文件也在其中,那么就會導(dǎo)致里面的cJSON結(jié)構(gòu)體按照1字節(jié)對齊,最終其結(jié)構(gòu)體大小為56個(gè)字節(jié)而已經(jīng)編譯好的cjson庫可并非如此,因此對于64位程序,它還是按照8字節(jié)對齊,結(jié)構(gòu)體大小為64字節(jié),而對于32位程序,按照4字節(jié)和1字節(jié)對齊,都是36字節(jié)。
同一個(gè)結(jié)構(gòu)體的大小竟然在不同的代碼中大小不一樣!
最終也就出現(xiàn)了我們遇到的情況,64位程序由于庫中申請結(jié)構(gòu)體內(nèi)存大小與外部調(diào)用不一樣,最終導(dǎo)致掛死,而32位程序解析JSON正常。
來源:公眾號編程珠璣博客:https://www.yanbinghu.com
總結(jié)
幸運(yùn)的是,本文示例中能夠很明顯的能看到問題所在,但在實(shí)際項(xiàng)目中,如果頭文件管理不規(guī)范,并且項(xiàng)目的產(chǎn)品多樣,通過編譯宏來隔開使用的頭文件,就很難發(fā)現(xiàn)這樣的問題。
思考
什么情況下需要1字節(jié)對齊呢?
附錄
本文完整代碼請查看字節(jié)對齊不慎引發(fā)的掛死問題的附錄部分。
微信公眾號【編程珠璣】:專注但不限于分享計(jì)算機(jī)編程基礎(chǔ),Linux,C語言,C++,數(shù)據(jù)結(jié)構(gòu)與算法,工具,資源等編程相關(guān)[原創(chuàng)]技術(shù)文章。總結(jié)
以上是生活随笔為你收集整理的对齐方式有那些_字节对齐不慎引发的挂死问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 做python项目需要知道什么_一文带你
- 下一篇: 静态库调用_静态链接和动态链接对比简析