0x80000002: Datatype misalignment.
同樣的程式在 x86 上不會有這個的問題(但會對效率有影響)。這個 Exception 在這篇有更多的說明,所謂的記憶體對齊的問題,似乎除了 x86 以外的 CPU 都有這樣的限制,就是在存取記憶體時會依要存取的大小而必需要對齊適當的起點,例如要存取 DWORD 的變數,一定要依 4 倍數的記憶體起點對齊,而 WORD 要對齊 2 的變數,而如果是 BYTE 的話就不會有這樣的問題。正常情況下 Compiler 不會弄出違反這個規則的 code ,但如果是自己對 pointer 強制轉型就要小心這樣的問題,像下面的程式就會出問題:
int a ; char *p = (char*)&a ; int *pp = (int*)(p+1) ; int b = *pp ;
回到 BMP 檔頭的問題,BMP 檔案是像下面的格式:
基本上讀取的程式是類似這樣:
PBITMAPFILEHEADER pbmfh = (PBITMAPFILEHEADER)(bmpfile.GetFileContent()); PBITMAPINFO pih = (PBITMAPINFO)(pbmfh+1); int b = (pih->bmiHeader).biSize ;
結果問題就出在 BITMAPFILEHEADER 的大小是 14 ,非 4 的倍數,就會造成讀取其下 BITMAPINFO 時造成不對齊的情況。這個問題治本的解法是在定 struct 就要小心,不要弄出這種容易造成問題的結構。而治標的方法有使用 __unaligned 來避免這個問題,不過我覺得直接把他 co 一份出來用比較方便。
BITMAPINFO bmi ; memcpy(&bmi, (BITMAPINFO*)(pbmfh + 1), sizeof(bmi));
至於 co 的時候為什麼不會造成 misalignment 呢?因為 memcpy 時是 byte-wise copy,而 byte 不會有 misalignment 的問題了。
0 comments:
Post a Comment