Ошибка: недопустимый аргумент типа унарного ‘*’ (имеет ‘long int’)

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

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

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

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

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

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

0x7ffeae3b3674

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

Какое значение хранится в памяти 0x7fffdf222fec? На основании этого вы можете привести его к указателю определенного типа.

kiran Biradar 24.05.2019 09:47

что заставляет вас думать, что литерал является указателем?

ΦXocę 웃 Пepeúpa ツ 24.05.2019 09:47

значение какого типа хранится в ячейке памяти?

n. 1.8e9-where's-my-share m. 24.05.2019 09:51

Вы можете разыменовывать только те значения, которые имеют тип указателя. Либо переменная типа указателя, либо результат приведения к типу указателя.

Gerhardh 24.05.2019 09:52

Что заставляет вас думать, что адрес a будет тем же самым, когда вы снова запустите программу? И еще более интересно: почему вы думаете, что в том же месте зарезервирована память, если в вашей функции больше нет переменных?

Gerhardh 24.05.2019 09:53

В Linux-системе void main() однозначно неверно. Это должно быть int main(void) для предпочтения или int main(), если вы действительно настаиваете.

Jonathan Leffler 24.05.2019 09:54
youtube.com/watch?v=Rxvv9krECNw&t=12m0s
sobha 24.05.2019 09:54

@Gerhardh, я посмотрел это видео и написал эту программу, я не знал, что

sobha 24.05.2019 09:55

Отредактируйте дополнительную информацию в вопросе, пожалуйста. Также объясните, что люди могут ожидать увидеть на другом конце вашей ссылки на YouTube. Также было бы полезно/разумно, если бы в вашем коде и комментариях использовался согласованный адрес. У вас на дисплее как минимум два: 0x7fffdf222fec и 0x7ffeae3b3674.

Jonathan Leffler 24.05.2019 09:56
int a; void* vp = &a; printf("\n %p ",vp); будет одним из способов сделать это правильно.
P.W 24.05.2019 09:57

@P.W не могу распечатать ненужное значение в определенном месте

sobha 24.05.2019 10:00

@Jonathan Leffier. Извините, я изменю его на первый адрес

sobha 24.05.2019 10:01

@sobha нет, вы не можете прочитать содержимое произвольного адреса на современной платформе с управлением памятью. Это либо приведет к segfault (сбою программы), либо если случайно адрес будет доступен из вашей программы, вы получите все, что было сохранено по этому адресу.

Jabberwocky 24.05.2019 10:35
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
13
338
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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

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

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

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

Cannot i access values at this location using this way?

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

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

Вы можете прочитать больше об ошибках сегментации здесь

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

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

I wrote a program like this and got the address of a as

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

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

Извините, Броман, я попробовал это #include<stdio.h> int main(){ printf("\n %d ",(инт)(0x7ffeae3b3674)); вернуть 0; } ./a.out, но я получаю ошибку сегментации (дамп ядра)

sobha 24.05.2019 10:34

@sobha прочитайте другие ответы и комментарии, особенно последнее предложение этого ответа.

Jabberwocky 24.05.2019 10:37
Ответ принят как подходящий

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

Это просто потребует, чтобы вы преобразовали это простое значение адреса в указатель.

Что-то такое:

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

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

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

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

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

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

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

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

спасибо, Герхард, за то, что хватило терпения объяснить это. теперь я думаю, что понял. спасибо

sobha 24.05.2019 10:05

@Gerhardth, я пробовал это, но получаю .. ./a.out Ошибка сегментации (сброс ядра)

sobha 24.05.2019 10:11

не могли бы вы сказать мне, почему я получаю эту ошибку при попытке сделать это

sobha 24.05.2019 10:12

Как я уже упоминал: адрес не ваш, и доступ к нему не определен. Если вам повезет, UB приведет к segfault.

Gerhardh 24.05.2019 10:25

@Gerhardth, я могу узнать, какое адресное пространство зарезервировано для конкретной программы?

sobha 24.05.2019 10:28

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

Gerhardh 24.05.2019 10:35

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

Gerhardh 24.05.2019 10:54

Давайте продолжить обсуждение в чате.

sobha 24.05.2019 11:35

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

Цитата из ИСО9899, 6.2.5 Типы p1,

The meaning of a value stored in an object or returned by a function is determined by thetypeof the expression used to access it.

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

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

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

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

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

Большое спасибо, alinsoar. Впервые слышу о readelf

sobha 24.05.2019 10:46

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