日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

对齐方式有那些_字节对齐不慎引发的挂死问题

發(fā)布時(shí)間:2024/10/8 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 对齐方式有那些_字节对齐不慎引发的挂死问题 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言

之前程序是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)致的呢?
問題的根源在于下面這幾行代碼:

#pragma pack(1) #include"cJSON.h" #pragma pack()

另外補(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)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。