當我有如下用戶定義的型別時:
typedef struct MyData_t {
uint16_t val;
...
} MyData;
還有一個簡單的陣列,我想用它來存盤不同型別的結構:
uint8_t buffer[];
然后我想創建一個結構指標,它使用陣列來存盤該結構的資料:
MyData* freelist = (MyData*) buffer;
然后我得到 MISRA 2012 錯誤:
注釋 9087:在指向物件型別的指標和指向不同物件型別的指標之間執行轉換 [MISRA 2012 Rule 11.3,必需]
這條規則說由于可能的對齊問題,在不同型別的物件之間轉換指標是不安全的。我的問題是:在嵌入式環境中,編譯器在這種情況下引起任何問題的常見程度如何?當被迫保留實作概念(關于存盤不同型別物件的緩沖區陣列)時,我該如何防止這些問題?
uj5u.com熱心網友回復:
如果您取消參考freelist,那么您將呼叫未定義的行為。兩者都是因為可能的對齊問題以及嚴格的混疊。這是一個錯誤,MISRA 或沒有 MISRA。最簡單的解決方法是memcpy改用。
在這種情況下,編譯器在嵌入式環境中引起任何問題的情況有多普遍?
在對齊的情況下,它取決于硬體。像 MIPS 這樣的架構對對齊非常挑剔,而像通用 8 位 MCU 等其他架構則不在乎。
至于嚴格別名錯誤,當 gcc 編譯器開始在嵌入式系統中流行時,在 2008-2010 年 ARM 炒作年開始時(gcc 版本大約 3 .x 什么東西?)。現代 gcc 版本的別名錯誤優化不那么嚴格。使用 gcc 時仍然總是編譯-fno-strict-aliasing,因為編譯器不穩定并且在允許嚴格別名時使用通常很危險。
至于常規的嵌入式系統編譯器,他們通常不會愚蠢到濫用嚴格的別名優化,因為他們想出售他們的編譯器。
值得注意的是,反過來——從結構到字符指標——也很好。MISRA C:2012 11.3 然后列出以下顯式例外:
例外
允許將指向物件型別的指標轉??換為指向物件型別char、signed char或unsigned char之一的指標。
uj5u.com熱心網友回復:
在這種情況下,編譯器在嵌入式環境中引起任何問題的情況有多普遍?
足夠常見,因為它無法滿足對齊需求。例如。buffer[]可能存在于奇數地址上,訪問uint16_t需要偶數地址。結果:總線違規。任何鑄造都無濟于事。
我怎樣才能防止這些問題
使用 aunion和來對齊uint8_t[]并struct MyData_t避免混疊問題。
uj5u.com熱心網友回復:
您可以通過首先將其轉換為void*指標來規避該錯誤。
話雖如此,它仍然是實作定義的行為,因此違反了 MISRA 指南。void*只有當您轉換為完全相同的型別并回傳到完全相同的型別時,您才能保證按照標準的有效性。
然而,在嵌入式系統中可能經常存在需要這樣做的情況,例如。訪問特定的記憶體區域。我至少吃過一些。在這些情況下,您需要根據 MISRA 由管理層簽署此用途。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/485089.html
下一篇:這個工會合法嗎?
