DWORD и DWORD_PTR на 64-разрядной машине

#windows #winapi #mfc

#Windows #winapi #mfc

Вопрос:

В Windows API добавлено несколько *_PTR типов для поддержки 64-разрядной адресации Win64.

 SetItemData(int nIndex,DWORD_PTR dwItemData)
  

Этот API работает как для 64, так и для 32-разрядных машин, когда я передаю второй параметр как DWORD .

Я хочу знать, произойдет ли сбой этого конкретного API на 64-разрядной машине, если я передам второй параметр как DWORD . Как я могу протестировать сценарий сбоя?

Спасибо, Нихил

Ответ №1:

Функция не завершится ошибкой, если вы передадите DWORD , потому что она вписывается в DWORD_PTR . Однако указатель гарантированно помещается в a, DWORD_PTR но не в a DWORD на 64-разрядных платформах.

Таким образом, этот код правильный:

 int *before_ptr = new int;
yourListBox.SetItemData(index, (DWORD_PTR) before_ptr);
int *after_ptr = (int *) yourListBox.GetItemData(index);
ASSERT(before_ptr == after_ptr);  // Succeeds.
delete after_ptr;                 // Works.
  

Но этот код неверен и автоматически усекает указатель до младших 32 бит:

 int *before_ptr = new int;
yourListBox.SetItemData(index, (DWORD) before_ptr);
int *after_ptr = (int *) yourListBox.GetItemData(index);
ASSERT(before_ptr == after_ptr);  // Fails.
delete after_ptr;                 // Undefined behavior, might corrupt the heap.
  

Комментарии:

1. Вы правы, указатель не поместится в DWORD на 64-разрядной версии, и это приведет к усечению указателя. Как я могу протестировать этот сценарий сбоя, когда мой указатель будет обрезан, и я получу нежелательное значение.

2. Я пробовал это, но я не получаю никакого утверждения: ‘CString str(«»); for (int i=0; i < 20; i ) { str.Format(_T(«строка элемента%d»), i); XcomboCtr. Добавить строку( str ); } int before_ptr = новый int; BOOL bsetItemData= XcomboCtr. SetItemData(0, (DWORD)before_ptr); int *after_ptr = (int )(XcomboCtr. GetItemData(0)); ASSERT(before_ptr == after_ptr); // Сбой. удалить after_ptr; ‘

3. @Nikhil, предполагая, что вы создаете в режиме отладки ( ASSERT не будет скомпилирован в режиме выпуска), это может означать, что все верхние 32 бита вашего указателя равны нулям. В этом случае это сработает, но вы не можете гарантировать, что все ваши указатели будут такими.