Едно преобразуване може да превърне привидно обикновен помощник за настройки на прокси в зависим от архитектурата отказ:

current = (IntPtr)((int)current + optionSize);

Този код стеснява естествен адрес до 32-битово цяло число, преди да добави размера на следващата структура. 64-битов процес може да съдържа адреси, които не се побират. В зависимост от преобразуването и стойността резултатът може да е изключение за препълване или невалиден адрес. Връщането на компилацията към x86 може да скрие грешката, но оставя interop реализацията зависима от този заобиколен подход.

Пазете адресите във форма с размер на указател. Например, придвижването през вече заделен масив може да използва:

IntPtr item = IntPtr.Add(buffer, checked(index * optionSize));

Отместването остава цяло число; самият адрес не се притиска през него. Размерът на заделянето и индексът все още трябва да са валидни.

След това прегледайте околните декларации

Опциите на WinINet за всяка връзка съдържат обединение, чиито членове включват DWORD, указател към низ и FILETIME. Полетата-указатели се нуждаят от IntPtr; полетата DWORD остават 32-битови. Естественото подравняване е от значение, затова заместването на всяко цяло число с 64-битово цяло или налагането на пакетирано разположение не е правилен ремонт.

Използвайте размера на структурата след маршалинг, когато обхождате масива, съгласувайте последователно декларацията ANSI или Unicode и проследявайте всяко заделяне отделно. Освобождаването на блока от структури за опции не освобождава автоматично низове, заделени другаде и посочени от тези структури.

Накрая, отделете въпроса за обхвата на настройките от коректността на паметта. Поправянето на преобразуване не доказва, че избраната от помощника опция на WinINet засяга само един контрол, един процес или настройките на текущия потребител. Проверете това поведение на API, преди да приемете останалата част от стар пример. Ако той също изпраща известия за обновяване, изберете ги за предвидения обхват.

Подобни статии