Получение NULL при побитовой конъюнкции

92
08 января 2022, 06:20

В проекте есть следующий код:

#define SIZE 4096U
...
void *t_ptr = (void *) (*(uintptr_t *) test->field & ~(SIZE - 1U));

С помощью него необходимо получить указатель на первый элемент списка, так как память изначально была выделена с выравниваем SIZE.

Адрес может быть, например, таким - 0x460028.

Однако результат выполнения этой строки равен NULL. Странность заключается в том, что при использовании другого указателя код вполне себе успешно функционирует.

test - это структура, описывающая некую область памяти. field - указатель на другую вспомогательную структуру.

struct Test {
    ...
    struct Field *field;
};
struct Field {
    ...
    Test *test;
};
Test *test = (Test *) mem;
test->field = (Field *) mem1;

В данном случае, при ptr равном 0x4a0028, будет возвращено 0x4a0000.

ptr - обычный указатель - void *

#define SIZE 4096U
...
void *t_ptr = (void *) (*(uintptr_t *) ptr & ~(SIZE - 1U));
Answer 1
void *t_ptr = (void *) (*(uintptr_t *) ptr & ~(SIZE - 1U));

Выражение *(uintptr_t *) ptr означает «привести указатель ptr к типу ″указатель на uintptr_t″, а затем разыменовать» т.е. его результатом будет содержимое того участка памяти, на который указывает ptr, интерпретированное как целое uintptr_t.

Для того, чтобы получить значение указателя привидённое к uintptr_t надо сделать просто (uintptr_t) ptr.

Также если sizeof(uintptr_t) > sizeof(unsigned), то выражение ~(SIZE - 1U) перед выполнением побитового И будет расширено до uintptr_t по правилам беззнакового расширения т.е. даст число вида 0x_0000_0000_ffff_e000 вместо полностью заполненной битовой маски старших разрядов. Чтобы этого избежать надо привести выражение к uintptr_t до побитового НЕТ.

В итоге получение адреса страницы на которую указывает указатель должно выглядеть как-то так:

void *t_ptr = (void *) ((uintptr_t) ptr & ~((uintptr_t)SIZE - 1U));
READ ALSO
C++ Применение cin.getline к двумерным массивам char

C++ Применение cin.getline к двумерным массивам char

Вопрос таков - какие есть решения?

144
Почему нет доступа к полям MyIterator?

Почему нет доступа к полям MyIterator?

Я пишу вторую версию вставки в map, где нужно передавать ещё и итератор, помимо вставляемой пары, то есть пишу аналог такой вставки:

195
Башня || Олимпиада ACM-ICPC

Башня || Олимпиада ACM-ICPC

Есть вопрос к задаче по алгоритмическому программированию:

218