![](/img/trans.png)
[英]What is the workaround for unaligned memory access exception on ARM9 using C?
[英]ARM unaligned memory access workaround
我必須將源代碼移植到運行Linux的ARM平台。 不幸的是,我遇到了未對齊的內存訪問問題。 源使用指針強制轉換和訪問。
像下面這樣的代碼像病毒一樣遍布代碼庫。 由於gcc -Wcast-align
命令行選項,我可以查明有問題的位置,但是有超過一千個實例要經歷。
u = (IEC_BOOL);
(((*(IEC_LINT*)pSP).H < b.H)
|| (((*(IEC_LINT*)pSP).H == b.H) && ((*(IEC_LINT*)pSP).L < b.L) )) ? 1 : 0);
*(IEC_DWORD OS_SPTR *)pSP =
(IEC_DWORD)(*(IEC_DWORD OS_SPTR *)pSP >> u);
*(IEC_DWORD OS_SPTR *)pSP =
(IEC_DWORD)(*(IEC_DWORD OS_SPTR *)pSP << -u);
u = (IEC_BYTE)((*(IEC_DINT*)pSP != b) ? 1 : 0);
*(IEC_DWORD*)pSP = (IEC_DWORD)(*(IEC_DWORD*)pSP & w);
(*(IEC_ULINT*)pSP).H += u.H;
(((*(IEC_ULINT OS_SPTR *)pSP).H == b.H)
&& ((*(IEC_ULINT OS_SPTR *)pSP).L > b.L))) ? 1 : 0);
u = (IEC_BYTE)((*(IEC_REAL*)pSP >= b) ? 1 : 0);
使用echo 2 > /proc/cpu/alignment
on會使Linux內核修復問題,但應用程序的性能會降低到不再可接受的程度。
我在網上搜索了類似於GCC(v4.4.1)編譯器的__unaligned
或__packed
關鍵字,但截至目前為止空了。
我認為很多問題的代碼行可以通過一個或多或少復雜的正則表達式/替換來修復,但是現在,經過一段時間的努力,我看到,這種方法也將需要大量繁瑣的工作。
你們有什么建議如何完成這項工作? 我認為一個gcc 4.5編譯器插件會有點矯枉過正但是有沒有比正則表達式好的東西? 您能提出哪些其他建議? 不一定所有問題實例都必須修復,因為我仍然可以依賴內核來處理一些罕見的情況。
有__attribute__((__packed__))
這可能在某些情況下有所幫助,但我真的認為這段代碼應該比以后更早清理,因為你可能會花更多的時間解決問題而不是修復它一勞永逸。
哇,這是一個不聖潔的混亂。 擺弄編譯器不會讓你到處都是。 代碼在所有體系結構上都是非法的,但恰好在某些體系結構上工作(例如x86)。 我會修復代碼本身。
可悲的是,沒有辦法做到這一點。 但是,您可以通過一長串搜索和替換獲得很長的路要走,然后手動修復其余部分。 我首先刪除這些數據類型的聲明,所以如果你編譯錯過的任何代碼,那就錯了。 然后,搜索和替換“*(IEC_DWORD OS_SPTR *)pSP =”與“set_dword(pSP,” 。)使用內聯函數“set_dword”來做正確的事情。繼續執行盡可能多的易於更換的代碼段。你可以想象。仍然有大量的手工修理。
我能想到的唯一另一種方法就是編譯器插件,正如你的建議,並使整個編譯單元中的每個指針都有對齊1.編譯器然后將字節加載/存儲所有內容。 它最終可能不僅僅是你想要的代碼。 這可能不像聽起來那么容易實現。
我們可以假設問題源於ARM是32位機器而Linux盒子以64位模式運行的事實,或者代碼可以假設它是在16位機器上運行。
一種方法是查看訪問的底層結構。 成員“H”和“L”可能是32位類型,可以像64位一樣進行訪問。
嘗試修改L和H的類型以使代碼表現得更好。
(不可否認,這是一個空洞,因為代碼片段沒有透露應用程序的細節,也沒有透露底層結構。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.