遭遇記憶體對齊問題

2021-05-27 22:07:01 字數 1837 閱讀 4353

先說理論的為何要記憶體對齊?

1、平台原因(移植原因):不是所有的硬體平台都能訪問任意位址上的任意資料的;某些硬體平台只能在某些位址處取某些特定型別的資料,否則丟擲硬體異常。

2、 效能原因:經過記憶體對齊後,cpu的記憶體訪問速度大大提公升。

圖一:這是普通程式設計師心目中的記憶體印象,由乙個個的位元組組成,而cpu並不是這麼看待的。

圖二:cpu把記憶體當成是一塊一塊的,塊的大小可以是2,4,8,16位元組大小,因此cpu在讀取記憶體時是一塊一塊進行讀取的。塊大小成為memory accessgranularity(粒度)本人把它翻譯為「記憶體讀取粒度」。

假設cpu要讀取乙個int型4位元組大小的資料到暫存器中,分兩種情況討論:

1、資料從0位元組開始

2、資料從1位元組開始

再次假設記憶體讀取粒度為4。

圖三:當該資料是從0位元組開始時,很cpu只需讀取記憶體一次即可把這4位元組的資料完全讀取到暫存器中。

當該資料是從1位元組開始時,問題變的有些複雜,此時該int型資料不是位於記憶體讀取邊界上,這就是一類記憶體未對齊的資料。

圖四:此時cpu先訪問一次記憶體,讀取0—3位元組的資料進暫存器,並再次讀取4—5位元組的資料進暫存器,接著把0位元組和6,7,8位元組的資料剔除,最後合併1,2,3,4位元組的資料進暫存器。對乙個記憶體未對齊的資料進行了這麼多額外的操作,大大降低了cpu效能。

這還屬於樂觀情況了,上文提到記憶體對齊的作用之一為平台的移植原因,因為以上操作只有有部分cpu肯幹,其他一部分cpu遇到未對齊邊界就

直接罷工了。

我所遇到的問題:

在專案中要按協議解析一接收到的字串,從中提取資料。

環境為msp430,裸奔程式。

剛開始使用的方法是,取串中對應資料段的首位址,將其強制轉換成目標資料的資料型別指標,再取其值,將該值賦予目標物件。

以下是示意**:

/*******************code start**********************/

// 找到指定資料的位址,pcsrcdata指向傳入的資料,my_data_idx是所需提取資料的相對位址

pcsrcdata += my_data_idx;

// 提取我所需要的資料

fmydata = *((float *)pcsrcdata);

/*******************code end**********************/

位址對齊,訪問成功,此情況純屬巧合;

位址未對齊,cpu具有在未對齊情況下,cpu依然支援通過多次訪問移位操作,對程式來說也可認為是成功的;

位址未對其,cpu也不支援未對齊情況下的糾錯處理。

很不幸,也很幸運,在測試時我就遇到了第三種情況。但又不完全相同,此時cpu仍在訪問,不過它對位址進行了調整,將其調整為四位元組對齊,這樣它是能正常訪問了,可我的資料卻提取錯了。

處理方法:

/*******************code start**********************/

// fmydata = *((float *)pcsrcdata);將此語句改為下面這句

memcpy(&fmydata , pcsrcdata, sizeof(float)

);/*******************code end**********************/

從這件事吸取的經驗是態度上要謹慎再謹慎,不能有僥倖心理。

記憶體對齊問題

一直困惑自己有兩個問題 1.程式為什麼要做記憶體對齊?1.處理器訪問記憶體是粒度為多位元組時,如果資料不是在邊界處,則,處理器需要分多個時鐘週期進行資料的訪問。2.增加可移植性。並非所有的處理器都可以訪問任何位址,可能出現硬體錯誤。具體可以參考 2.struct中如何計算記憶體對齊?先說說c語言中s...

記憶體對齊問題

首先由乙個程式引入話題 1 環境 vc6 windows sp22 程式13 include iostream 45 using namespace std 67 struct st1 8 1314 struct st215 20 21int main 2227 程式的輸出結果為 sizeof st...

記憶體對齊問題

一 什麼是位元組對齊,為什麼要對齊?現代計算機中記憶體空間都是按照byte劃分的,從理論上講似乎對任何型別的變數的訪問可以從任何位址開始,但實際情況是在訪問特定型別變數的時候經常在特定的記憶體位址訪問,這就需要各種型別資料按照一定的規則在空間上排列,而不是順序的乙個接乙個的排放,這就是對齊。對齊的作...