Случайный указатель C ++ - что он делает?

0

Я эксперт по программированию на С#, но я очень новичок в C++. Я понимаю основную идею указателей, но я играл. Вы можете получить фактическое целочисленное значение указателя, выставив его как int:

int i = 5;
int* iptr = &i;
int ptrValue = (int)iptr;

Это имеет смысл; это адрес памяти. Но я могу перейти к следующему указателю и передать его как int:

int i = 5;
int* iptr = &i;
int ptrValue = (int)iptr;
int* jptr = (int*)((int)iptr + 1);
int j = (int)*iptr;

и я получаю, казалось бы, случайное число (хотя это не очень хороший PSRG). Что это за номер? Это другой номер, используемый одним и тем же процессом? Возможно, это из-за другого процесса? Является ли эта плохая практика или запрещена? А если нет, есть ли для этого использование? Это классно.

  • 0
    Обратите внимание, что когда вы приводите указатель на int, а затем добавляете 1, это приведет к появлению в памяти другого значения, чем если бы вы добавили 1 к нему в качестве указателя. Когда вы добавляете 1 к int * , компьютер добавляет sizeof(int) к значению в памяти. Когда вы приводите его к int а затем добавляете 1, компьютер просто добавляет 1. (Или, по крайней мере, это то, что обычно происходит. При наличии неопределенного поведения компьютер может делать все, что угодно, и даже когда поведение определено компьютер должен делать только то, что дает те же видимые результаты, что и программа, которую вы написали.)
Теги:
pointers
int
memory-address

7 ответов

4

Что это за номер? Это другой номер, используемый одним и тем же процессом? Возможно, это из-за другого процесса?

Обычно вы не можете указывать указатели на целые числа и обратно и ожидать, что они будут неразрешимыми. Целые числа - это числа. Указатели - указатели. Они совершенно разные абстракции и несовместимы.

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

См. C++: безопасно ли указывать указатель на int и позже на указатель?

Является ли эта плохая практика или запрещена?

Недопустимое? Неа.
Плохая практика? Ужасная практика.

0

Вы определяете целое число

int i = 5;

Это означает, что вы выделяете пространство в стеке потоков и инициализировали его как 5. Затем вы получаете указатель на эту память, которая на самом деле является позицией в вашем текущем стеке стека,
и вы увеличиваете указатель на 1, что означает, что вы указываете на следующее место в стеке потоков, и вы анализируете его снова как целое число,

int* jptr = (int*)((int)iptr + 1);
int j = (int)*jptr;

Затем вы получите целое число из стека потоков, которое близко к тому, где вы определили int i.

Конечно, это не рекомендуется делать, если вы не хотите стать хакером и хотите использовать переполнение стека (здесь это означает, что это такое, а не имя сайта, ха!)

  • 0
    Вы можете использовать переполнение стека с этим? Я думал, что переполнение стека означает игру для моей программы.
  • 0
    Если вы используете memcpy для копирования огромного буфера в jptr или iptr, вы определенно можете сделать стек беспорядком, но если вы эксперт, вы можете использовать буфер, который может просто изменить адрес возврата, чтобы он указывал на вашу функцию. может делать свои "плохие" вещи, но не делай этого!
0

Вы обнаруживаете, что случайные места в памяти содержат "неизвестные" данные. Не только это, но вы можете обнаружить, что вы указываете на память, что ваш процесс не имеет "прав", так что даже акт чтения содержимого адреса может вызвать ошибку сегментации.

В общем случае вы выделяете некоторую память указателю (например, с malloc), вы можете взглянуть на эти местоположения (которые могут иметь случайные данные "в последний раз" в них) и изменить их. Но данные, которые явно не относятся к блоку памяти указателя, могут вести все короли неопределенного поведения.

Кстати, если вы хотите посмотреть "следующее" место, просто

NextValue = *(iptr + 1);

Не делайте кастинга - арифметика указателя знает (в вашем случае) именно то, что указано выше: "содержимое следующего я нахожу место".

0
int i = 5;
int* iptr = &i;
int ptrValue = (int)iptr;
int* jptr = (int*)((int)iptr + 1);
int j = (int)*iptr;

1) вы можете наложить int на указатель и обратно, и он даст вам то же значение

2) Возможно ли это из другого процесса? нет, нет, и вы не можете получить доступ к памяти другого процесса, кроме использования readProcessMemmory и writeProcessMemory под win32 api.

3) вы получаете другой номер, потому что вы добавляете 1 к указателю, пытаетесь выставить 1, и вы будете иметь такое же значение.

0

Это не "случайный". Это просто означает, что есть некоторые данные по следующему адресу.

Чтение 32-битного слова из адреса A будет копировать байты в A, A + 1, A + 2, A + 3 в регистр. Но если вы разыскиваете int при A + 1, тогда CPU загрузит байты от A + 1 до A + 4. Поскольку значение A4 неизвестно, это может заставить вас думать, что число "случайное",

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

0

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

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

int arr[5] = {1, 2, 3, 4, 5};
int *p = arr;

printf("%d", *p); // this will print 1

p++; // pointers arithmitics

printf("%d", *p); // this will print 2
0

Вы переходите за пределы i указателя на 4 или 8 байтов и распечатываете номер, который может быть другим номером, хранящимся в вашем программном пространстве. Значение неизвестно, и это неопределенное поведение. Также есть хорошая вероятность, что вы можете получить сообщение об ошибке (это означает, что ваша программа может взорваться) [Когда-либо слышал о SIGSEGV? Проблема нарушения сегментации]

Ещё вопросы

Сообщество Overcoder
Наверх
Меню