[問題] union 的undefine behavior

作者: lovejomi (JOMI)   2020-06-16 00:35:43
平常真的很少用union 所以當要用的時候還是查了一下
https://en.cppreference.com/w/cpp/language/union
S s = {0x12345678}; // initializes the first member, s.n is now the active
member
// at this point, reading from s.s or s.c is undefined behavior
诶, 這不就是常看到union的標準用法嗎?
於是我再找找
http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Ru-pun
恩....真的是undefined behavior.....完全顛覆我之前對union的認知
原來看到這種union { struct{} , array;} 全部都是UB...
想問一下
1. 即使他是 書本上的UB 但是不是可以說 所有已知compiler實作上都讓他效果一致
也就是常用的那套手段也沒什麼問題, 真的這樣寫 也不用太苛責?
2. 如果真的不想寫出UB 的程式碼, 是不是只能用reinterpret_cast
例如
union Endian{
int a;
char b;
};
改用
int a = 1; char b = *(reinterpret_cast<char*>(&a));
對於reinterpret_cast每當用 都很怕是UB,
有沒有什麼通則可以快速確認是否轉型是UB呢?
以上 (今天才知道union 這樣寫是UB, 實在很震驚)
作者: loveme00835 (髮箍)   2020-06-16 02:09:00
你的認知應該是從 C 語言來的, 所謂的 active member就是已經建構好的物件, 如果你要改用另外一個物件就必須要先解構當前的 active member 再去建構另一個,在 C++ 裡所有物件都要經過建構才能用, 只有將指標轉型無視這個規則的都是 UB對於 non-class object 也是同理, 建構子/解構子一整套流程缺一不可如果懶得自己處理就改用 std::variant 吧
作者: lovejomi (JOMI)   2020-06-16 09:49:00
可是primitive type要怎麼建構解構(syntax)?如果要這樣 那之前在C work的union寫法 在C++是不是無法使用, 如我舉例的Endian 例子...連primitive type也UB?https://ideone.com/FjHpL0 這樣寫卻沒有建構子被呼叫合理嗎@@ 這樣我補上解構 不就不對稱了
作者: loveme00835 (髮箍)   2020-06-16 10:50:00
https://bit.ly/3d22Vlr 參考 [class.union]/6.3 還有[class.union]/7https://wandbox.org/permlink/q3ZZFikhmqHmmFSK
作者: lovejomi (JOMI)   2020-06-16 11:18:00
u.i.~int_t(); 我有私底下這樣寫但實在從來沒看過但這也證明了 endian那種用法在C++完全是個錯誤?但也像我第一個問題講的 這種UB真的是無法接受的嗎?您的例子 透過placement new才會有建構子呼叫如果一開始就要用 u.s 該怎麼辦呢https://wandbox.org/permlink/fmObYFTkDu6k6v3k是不是 要調整s為第一個 並且 在 {{一定要寫}} ?
作者: loveme00835 (髮箍)   2020-06-16 11:26:00
UB 是灰色地帶, 只要你確定使用的編譯器行為會如你預期, 那 UB 就只是可攜性比較差而已. 很多低階的記憶體操作都是 UB 要靠標準慢慢補完. 可以參考 [P0593]
作者: lovejomi (JOMI)   2020-06-16 11:50:00
恩 那 沒跑到建構子是不是也是可接受?
作者: loveme00835 (髮箍)   2020-06-16 12:51:00
當然不是這樣說 0rz 你沒有跑完 ctor 自然連 dtor 也不會跑, 尤其是對有 side-effect 的 ctor 來說更是一定要呼叫
作者: lovejomi (JOMI)   2020-06-16 19:18:00
我對side effect這詞用在這領域沒什麼感覺,可否給我一些延伸資訊呢 謝謝
作者: loveme00835 (髮箍)   2020-06-16 20:17:00
偶覺得你還是先把基礎打好
作者: CoNsTaR ((const *))   2020-06-21 11:02:00
想要有保障就用 inheritance,不要用 union 啊要用 union 就要自己人腦生成 induction principles 和檢查所有 introduction/elimination

Links booklink

Contact Us: admin [ a t ] ucptt.com