ошибка: недопустимый аргумент типа унарного * ’(имеет« long int ») - PullRequest
4 голосов
/ 24 мая 2019

Это небольшая программа, написанная мной для печати значения, хранящегося в ячейке памяти (0x7fffdf222fec). Я получаю error as 4:20: error: invalid type argument of unary ‘*’ (have ‘long int’ printf("\n %p ",*(0x7fffdf222fec));

Я использую компилятор gcc в Ubuntu 16.04. Мой ram составляет 4 ГБ. Не могу ли я получить доступ к значениям в этом месте, используя этот способ?

#include<stdio.h>
void main(){
    printf("\n  %p   ",*(0x7ffeae3b3674));
}

Ожидаемым результатом является значение нежелательной почты, хранящееся по адресу

Я написал такую ​​программу и получил адрес

#include<stdio.h>
void main(){
    int a;
    printf("%p",&a);
}

0x7ffeae3b3674

Затем я применил вышеуказанный адрес к первой программе.

Ответы [ 3 ]

5 голосов
/ 24 мая 2019

Измените *(0x7fffdf222fec) на *(int*)0x7fffdf222fec.

0x7fffdf222fec - константа с типом long int.Вы не можете разыменовывать типы без указателей, поэтому сначала вам нужно привести их к указателю.Какой указатель вы выберете, зависит от того, как вы хотите интерпретировать данные по этому адресу.Я выбрал int* для этого примера, но вы можете выбрать любой тип указателя, кроме void*.

Обратите внимание, что есть вероятность, что это приведет к segfault.Не делайте этого, если вы не уверены, что имеете доступ к этому местоположению.

Чтобы уточнить:

Не могу ли я получить доступ к значениям в этом месте, используя этот способ?

Ну, это зависит от того, что вы имеете в виду.Это правильный способ прочитать это конкретное место.Проблема в том, что у вас может не быть к нему доступа.

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

Подробнее о сбоях сегментации вы можете прочитать здесь

Получение доступа к произвольной части памяти довольно сложно и в значительной степени зависит от системы.На Unix-машинах это делается не так, как на Windows-компьютерах.

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

Я написал такую ​​программу и получил адрес a как

Вы не гарантированно получите тот же адрескаждый раз, когда вы запускаете программу.Если вы объявили переменную, у вас, очевидно, есть доступ к ней.Попробуйте запустить программу несколько раз.Скорее всего, вы будете каждый раз получать разные адреса.

Если у вас нет особых потребностей, таких как драйверы кодирования, ядра или встроенные системы, вам никогда не следует беспокоиться об абсолютных адресах.

2 голосов
/ 24 мая 2019

Вы не можете иметь значение, не имея типа.

Цитирование из ISO9899 , 6.2.5 Типы p1,

Значение сохраненного значенияв объекте или возвращаемом функцией определяется типом выражения, используемого для доступа к нему.

Вы пытаетесь разыменовать адрес 0x7ffeae3b3674, но не говорите ему, какой тип имеет объект из этогоадрес.

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

По указанному адресу, когда вы знаете, что там есть целое число, вам нужно сообщить ему, чтобы разыменовать объект типа int, сначала приведя адрес к указателю на целое числотакой, что оператор * для разыменования целого числа (а также использования %d для информирования printf о том, что переданный параметр является объектом типа int):

printf("\n  %d   ",*((int*)0x7ffeae3b3674))

Другая проблема, которая может возникнуть, заключается в том, что после получения адреса из первой программы вы не можете знать, будет ли компилятор после второй компиляции выделять переменную a тот же адрес или что сегмент памяти все еще действителен.Вы должны проверить это, используя readelf.

1 голос
/ 24 мая 2019

У меня возник соблазн поиска дублирующего вопроса о чтении значений с заданного адреса.

Для этого просто потребуется преобразовать это простое значение адреса в указатель.

Что-то в этом роде:

int *p = (int *)0x1000000;
printf("value=%d", *p);

Но ваш вопрос немного другой.

Обычно данный адрес используется для доступа к некоторым аппаратным регистрам или подобным.

В вашем коде есть дополнительные проблемы.

#include<stdio.h>
void main(){
  printf("\n  %p   ",*(0x7ffeae3b3674));
}

Прежде всего, это должен быть int main(void) в качестве правильного прототипа для main.

Второе: у вас нет типа указателя.Хотя вы можете решить эту проблему с помощью приведения, как показано выше, вы также пытаетесь распечатать его как указатель, используя %p.Но когда вы разыменовываете указатель, вам нужен тип значения, на которое он указывает.Вероятно, int в вашем случае.

Третье: адрес, который вы используете, бесполезен.Вы не можете предполагать, что определенная переменная находится по определенному адресу.Ваша программа может использовать разные адреса при каждой загрузке.Также переменная, которая была там в первом тесте, больше не присутствует в вашем новом тесте.Компилятор не будет резервировать память в этом месте.Что бы там ни хранилось, оно не принадлежит вам!Доступ к нему - UB.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...