Указатель Увеличение Разница B / W 32-битный и 64-битный

StackOverflow https://stackoverflow.com/questions/4277349

  •  28-09-2019
  •  | 
  •  

Вопрос

Я пытался запустить некоторые драйверы, закодированные для 32-битной Vista (x86) на 64-битном Win7 (AMD64), и он не работал. После многих отладки и удара и суда я сделал это, чтобы работать на последнем, но я не знаю причину, по которой это работает. Это то, что я сделал:

Во многих местах буферные указатели указывали на массив конструкций (разные в разных местах), а также для их увеличения, в некоторых местах использовался этот тип оператора:

ptr = (PVOID)((PCHAR)ptr + offset);

И в некоторых местах:

ptr = (PVOID)((ULONG)ptr + offset);

2-й один возвращал мусор, поэтому я изменил их все до 1-го. Но я нашел много образцов водителей в сети после второго. Мои вопросы:

  1. Где эти макросы определяются (Google не помог много)?
  2. Я понимаю, что все макросы P_ являются указателями, почему у указателя был указан в ueong? Как эта работа на 32-битной?
  3. PCHR очевидно, изменяет ширину в соответствии с окружающей средой. Вы знаете любое место, чтобы найти документацию для этого?
Это было полезно?

Решение

  1. они должны быть определены в Winnt.h (они находятся в SDK; не иметь DDK под рукой)
  2. Ulong не знает долго; На 32-битной системе это размер указателя. Таким образом, указатель может быть преобразован взад и вперед в ueong без потерь - но не так на 64-битной системе (где отличить значение, то будет урезать его). Люди отказываются от улонга, чтобы получить арифметику байта-байта (даже если это неопределенное поведение, как вы узнали)
  3. Указатель арифметики всегда работает в единицах базового типа, то есть в символах для PCHAR; Это приравнивает к арифметике байта
  4. Любая C-книга должна разработана на точной семантике указателя арифметики.

Другие советы

Причина, по которой этот код терпит неудачу на 64-битных, заключается в том, что он отличает указатели в Ulong. ULONG - это 32-битное значение, в то время как указатели на 64-битных являются 64-битными значениями. Таким образом, вы будете усекать указатель всякий раз, когда вы используете ueg Cast.

PCHAR CAST, предполагая PCHAR, определяется как char * Хорошо, при условии, что намерение состоит в том, чтобы увеличить указатель на явное количество байтов.

Оба макроса имеют одинаковое намерение, но только один из них действителен, где указатели больше 32 битов.

Указатель арифметики работает так. Если у тебя есть:

T *p;

И вы делаете:

p + n;

(где n - число), то значение p изменится n * sizeof(T).

Чтобы дать конкретный пример, если у вас есть указатель на DWORD:

DWORD *pdw = &some_dword_in_memory;

И вы добавляете один к нему:

pdw = pdw + 1;

Тогда вы указываете на следующий DWORD. Адрес PDW указывает на увеличение sizeof(DWORD), то есть 4 байта.

Макрос, которые вы упоминаете, используют отсюда, чтобы привести к коммутации адресов, которые они применяются к умножению на разные суммы. Это обычно делается только в низкоуровневом коде, который был передан буфером байта (или символа или пустоты), но знает данные внутри на самом деле какой-то другой тип.

ULONG определяется в Windef.h в Windows SDK и всегда является 32-битным, поэтому, когда вы бросаете 64-битный указатель в ULONG Вы обрезаете указатель на 32 бита.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top