I recently ran across a bug with an application ported to the x64 platform. After debugging the application the error turned to be due to integrals layout and casting. I think this is a typical example worth mentioning.
It starts with this definition:
#define COMBO_VALUE -99
which is used for a combo box with SetItemData:
pCombo->SetItemData(index, (DWORD)COMBO_VALUE);
Notice the cast to DWORD, which is an integral type represented on 32-bits both on x86 and x64. At a later point this value was retrieved and tested against COMBO_VALUE:
if (pCombo->GetItemData(pCombo->GetCurSel()) == COMBO_VALUE)
They key here is how the value of -99 is represented:
| 32-bit platform | 64-bit platform | |
|---|---|---|
| -99 | FFFFFF9D | FFFFFFFFFFFFFF9D |
| (DWORD)-99 | FFFFFF9D | FFFFFF9D |
| (DWORD_PTR)-99 | FFFFFF9D | FFFFFFFFFFFFFF9D |
| (DWORD_PTR)(DWORD)-99 | FFFFFF9D | 00000000FFFFFF9D |
GetItemData returns a DWORD_PTR, so FFFFFF9D becomes 00000000FFFFFF9D on x64. Then -99 is also interpreted as a DWORD. Thus the condition in the above if statement resolves to 00000000FFFFFF9D == FFFFFFFFFFFFFF9D on x64, which of course is false.
To fix the problem, the if statement should be re-written like this:
if ((DWORD)pCombo->GetItemData(pCombo->GetCurSel()) == COMBO_VALUE)
A very simply fix, but not so simple to spot the root of the problem when just reading the code.
I have to disagree…
This should be the correct solution:
pCombo->SetItemData(index, (DWORD_PTR)COMBO_VALUE);
if (pCombo->GetItemData(pCombo->GetCurSel()) == (DWORD_PTR)COMBO_VALUE)