14.06.05 21:49 14.06.05 21:49 // оригинал
При переходе на последний Stingray огреб пока не слишком понятный чудный глюк. За всю свою программистскую жизнь я видел их много, но на такое еще не напарывался. Интересно, сколько бы я его отлавливал лет так десять назад. Сейчас же тупиковые варианты отсеялись довольно быстро - и то большая часть времени ушла на продирание глаз, которым не хотелось верить.
Библиотечная функция вызывает мою виртуальную функцию, передавая ей указатель на некоторую здоровую структуру. Чуть попозже моя функция передает элемент этой структуры библиотечной функции, которая при этом успешно наворачивается. Просматривание Call stack приводит к неожиданному результату:
//bugtraq.ru/files/gluk.gif
А именно, при переходе от моей функции к библиотечной четко видно, как запарывается кусок структуры - при том, что указатель один и тот же, и он всего лишь передан из одной функции в другую. Будь память выделена на стеке, было бы более-менее понятно, куда копать, тут же какие-то полные чудеса - в зависимости от того, откуда смотрим на кусок памяти, он выглядит по-разному. Все, конечно, усугубляется тем, что и библиотека в dll, и моя функция в dll, но предыдущей версии библиотеки это особо не мешало.
Максимум, что пока приходит в голову, - что при сборке библиотеки и моего кода каким-то чудом вылезли какие-то одноименные подструктуры разного размера, что и сдвинуло все данные, но пока ничего похожего не нашел.
Update: очень перспективно выглядит структура tagLVITEMA, ровно после которой все накрывается - ее состав зависит от значения _WIN32_WINNT, а уж оно запросто могло быть разным. Ну хоть какая-то надежда...
Update 2: ну так и есть, два основных модуля системы начали делаться в такие лохматые времена, что в хедерах не было даже слов про _WIN32_WINNT (работает себе и работает, на фига трогать), которое уже давно при генерировании новых проектов устанавливается в 0х400 (как и в Stingray). А при его отсутствии срабатывает следующий чудный кусок кода из стандартных хедеров:
#ifndef _WIN32_WINNT
#ifdef WINVER
#define _WIN32_WINNT WINVER
#else
#pragma message("_WIN32_WINNT not defined. Defaulting to 0x0501 (Windows XP and Windows .NET Server)")
#define _WIN32_WINNT 0x0501
#endif
tagLVITEMA же определена так:
typedef struct tagLVITEMA
{
UINT mask;
int iItem;
int iSubItem;
UINT state;
UINT stateMask;
LPSTR pszText;
int cchTextMax;
int iImage;
LPARAM lParam;
#if (_WIN32_IE >= 0x0300)
int iIndent;
#endif
#if (_WIN32_WINNT >= 0x501)
int iGroupId;
UINT cColumns; // tile view columns
PUINT puColumns;
#endif } LVITEMA, *LPLVITEMA;
В результате вызываемая функция считала, что в структуре на три поля больше, чем ей реально передавалось, и все работало с баальшими нюансами (самое забавное, что иногда таки запускалось и почти нормально жило).