2012-04-03 70 views
5

我有一個旨在存儲用戶定義的數據(即從一個插件)的結構。它有一個這樣的char[]與給定的最大大小來存儲該數據。類型雙引號,char []和解引用

struct A 
{ 
    // other members omitted 
    // data meant to be type punned, only contains PODs 
    char data[256]; 
}; 

然後有一個示例用戶結構具有一個靜態函數來從A投射自己。

struct B 
{ 
    int i; 
    double d; 

    static B& FromA_ref(A& a) 
    { 
     // static_assert that sizeof(B) < sizeof(A::data) 
     return * reinterpret_cast<B*>(a.data); 
    } 
}; 

我編譯g++ -O3 -std=c++0x -Wall -o test test.cpp(GCC 4.6.1)。

這會觸發dereferencing type-punned pointer will break strict-aliasing rules警告。我認爲這樣可以,因爲我使用了char[]作爲存儲,我認爲它會遵循與char*相同的規則。我發現它並不奇怪。你不是嗎?那麼......我現在不能改變它,所以讓我們繼續。

現在讓我們來看看下面的方法:

struct B 
{ 
    .... 
    static B* FromA_ptr(A& a) 
    { 
     // static_assert that sizeof(B) < sizeof(A::data) 
     return reinterpret_cast<B*>(a.data); 
    } 
} 

因爲我不是在這裏提領任何GCC不輸出任何警告。當我稍後使用指向B的指針時也不會。

A a; 
auto b = B::FromA_ptr(a); 
b->i = 2; // no warnings. 

但是安全嗎?我覺得我一直在解決問題而不是解決問題。對我來說,->仍然以某種方式解引用變量。

另外,有沒有更好的方法來實現效果? I.E.從另一個結構中的存儲獲得一個可修改的引用(或指針)? (Union不起作用,因爲當定義了A時,存儲的類型集是不知道的,有些可能通過插件添加,memcpy將迫使我來回複製數據,儘管它似乎是唯一安全的方式遠)

+0

我不是專家,但你在尋找'__may_alias__'屬性嗎? http://blog.worldofcoding.com/2010/02/solving-gcc-44-strict-aliasing-problems.html – 2012-04-03 01:14:36

+0

無論如何,你如何處理對齊問題? – curiousguy 2012-07-11 07:12:56

+0

@curiousguy:到目前爲止我不,但我應該。儘管如此,在x86上我猜我可能會降低性能。我希望'__attribute __((aligned(8)));'因爲我不想自動向量化任何東西,所以就夠了。可能'may_alias'已經告訴GCC在做太多奇怪的事情之前要注意對齊。 – 2012-07-12 06:21:26

回答

3

答案是否定的,它是不是安全(見本SO question

GCC將假設指針不能別名。例如,如果您通過一個分配然後從另一個分配讀取,GCC可以作爲優化對讀取和寫入進行重新排序 - 我已經看到這種情況發生在生產代碼中,調試並不令人愉快。所使用的類型

屬性((may_alias))可能是你可以得到禁止用於特定的代碼段的假設最接近的一次。