簡體   English   中英

C語言中任意內存的類型

[英]A type for arbitrary memory in C

這是參考這個問題

如何正確實現c malloc / realloc函數?

接受的答案提到可以使用char數組對任意內存池進行建模。

但是,對該已接受答案的評論之一指出

沒有分配存儲時間的char數組只能以字符類型作為別名。 換句話說,它不能也不應用作任意內存

這個對嗎? 如果是這樣,那么可以使用什么呢? 我想避免使用alloc或任何特定的OS調用-所以我對這個問題持對稱態度。

周圍有不同的問題。 首先,如@Magisch的答案所示,相關問題是返回一個懸空指針,導致未定義行為和一般執行錯誤。

第二個與@ ^ *#(此處為檢查)嚴格的別名規則相關。 當您將字符數組用作大緩沖區以從中分配任何類型時,如果您確保正確對齊,則普通編譯器會生成正確的代碼。 畢竟,這是他們必須實現mallocreallocfree例程的方式。 而且,由於它們是托管環境 (C標准庫)的一部分,因此編譯器開發人員還不足以禁止其使用。

但是C標准在這里更加嚴格。 您應該在此處閱讀我對類似問題的答案,尤其是@EOF對它的評論:

您不能將聲明為char []的對象的一部分打包為其他類型(字符類型除外)的對象,因為它們確實具有聲明的類型...這意味着從技術上講,您不能在純C語言中實現malloc()

別名是指嚴格的別名規則該規則控制如何允許編譯器使用寄存器。 如果您具有指向同一存儲器位置的不同類型的指針,則在通過另一種指針類型進行讀取時可能不會注意到通過一種指針類型完成的寫入,因為允許編譯器將數據緩存在寄存器中。

當您實現一個內存池時,這個問題通常是沒有解決的,因為該池實現不會對內存進行讀/寫操作。

如果要使用任意類型,那么最安全的選擇是聯合。 它不僅會“擊敗”嚴格的別名規則,還將確保正確的對齊方式。 請記住, malloc和Friends確保適合任何類型的對齊方式,而auto不適合。

問題是對齊。 在具有對齊限制的處理器上, char數組可能不會從適合於存儲較大對象(例如intdouble的地址開始。

為了安全起見,您需要確保char數組對於任何類型都正確對齊。 如果您使用的是C11編譯器,則可以像這樣強制對齊

#include <stddef.h>
#include <stdalign.h>

_Alignas(max_align_t) char buffer[SIZE];

對於較舊的編譯器, __attribute__((aligned(SIZE)))可能是一個解決方案。 否則,您需要查找強制對齊的#pragma

而且,正如在各種注釋/答案中所討論的,您絕對應該使用-fno-strict-aliasing選項禁用嚴格的別名優化。 如果該選項(或等效選項)不存在,則需要確定依賴於嚴格別名規則的優化級別,並且僅使用較低的優化級別。

我認為他指出的問題是,如果您靜態分配一個char類型的數組,然后使用像gcc這樣的現代,類似於桌面的C編譯器來編譯您的庫,則無法輕松地將該區域的內容轉換為另一種類型。 因為這樣編譯器將基於指針別名執行優化並將所有事情搞砸,因此請參閱“嚴格的別名規則”

只需確保您的編譯器不使用嚴格的別名就可以了。 例如,市場上沒有一個普通的嵌入式系統編譯器可以做到這一點。

使用gcc時,您將編譯為-fno-strict-aliasing 始終為可能導致此類問題的代碼啟用警告可能會很有用-Wstrict-aliasing

附帶說明一下,將uint8_t用作泛型類型更有意義,因為與char不同,它是完全明確的:它沒有簽名,並且大小是眾所周知的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM