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