Примеры из MSDN

Есть такая интересная библиотека от microsoft-а, под названием "Debugging Tools for Windows", а в ней есть такая функция для чтения имени идентификатора по его адресу (например имени функции по точке входа). И определена эта функция таким вот образом:

BOOLIMAGEAPISymGetSymFromAddr64( __in HANDLE hProcess, __in DWORD64 qwAddr, __out_opt PDWORD64 pdwDisplacement, __inout PIMAGEHLP_SYMBOL64 Symbol

);

  1. if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64)
  2. define SymGetSymFromAddr SymGetSymFromAddr64
  3. else
BOOLIMAGEAPISymGetSymFromAddr( __in HANDLE hProcess, __in DWORD dwAddr, __out_opt PDWORD pdwDisplacement, __inout PIMAGEHLP_SYMBOL Symbol );
  1. endif

Все бы хорошо есть 32-битный и 64-битные варианты, дефайн для переключения, но в злосном мсдн написана надпись: "Note This function is provided only for compatibility. Applications should use SymFromAddr." А еще добавили в комменты многообещающую фразу: "SymFromName and SymFromAddr provide much more detailed info on the returned symbol". В предвкушении, смотрим что ж они такого нового предлагают:

BOOLIMAGEAPISymFromAddr( __in HANDLE hProcess, __in DWORD64 Address, __out_opt PDWORD64 Displacement, __inout PSYMBOL_INFO Symbol

);

BOOLIMAGEAPISymFromAddrW( __in HANDLE hProcess, __in DWORD64 Address, __out_opt PDWORD64 Displacement, __inout PSYMBOL_INFOW Symbol

);

  1. ifdef DBGHELP_TRANSLATE_TCHAR
SymFromAddr SymFromAddrW
  1. endif

Замечательно, неизвестно куда изчез 32-битный вариант функции, зато появился непонятно кому нужный юникодовский. Положа руку на сердце, скажите честно какой код вы пишете чаще 32-битный код или код с поддержкой юникода? А еще много ли вы видели идентификаторов в программах, которые были бы записаны в кодировки отличной от ascii? Кароче, чем они руководствовались при этом рефакторинге не понятно совершенно.

Но на этом сюрпризы не заканчиваются. Смотрим официальный пример по использованию этой функции:

DWORD dwAddress;

DWORD dwDisplacement;

ULONG64 buffer[(sizeof(SYMBOL_INFO) + MAX_SYM_NAME*sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)];

PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;

pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);

pSymbol->MaxNameLen = MAX_SYM_NAME;

if (SymFromAddr(hProcess, dwAddress, &dwDisplacement, pSymbol)){// SymFromAddr returned success}else{ // SymFromAddr failed error = GetLastError(); printf("SymFromAddr returned error : %d\n", error);

}

dwAddress и dwDisplacement объявлены 32-битными DWORD-ами, хотя должны быть 64-битными DWORD64 типами. Ладно с dwAddress там передача идет через значение. Но на dwDisplacement с передачей по ссылке (а это уже чревато как минимум коруптом стека) ругается даже компилятор:

: error C2664: 'SymFromAddr' : cannot convert parameter 3 from 'DWORD *__w64 ' to 'PDWORD64'

Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

Во-первых это явственно показывает, что даже специалисты микрософта не понимают нафига был убран 32-битный вариант. Во-вторых мне очень интересно - проверяют ли мелкомягкие свои примеры в мсдн если уже не на логические ошибки, то хотя бы на ошибки компиляции.

Последняя правка: пт, 11/01/2008 - 18:21
Submitted by Victor on

GameDev.by