Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.89/19: Рейтинг темы: голосов - 19, средняя оценка - 4.89
155 / 9 / 1
Регистрация: 14.08.2019
Сообщений: 768
1

Как будет &(PVOID&) в reinterpret_cast?

21.08.2021, 03:27. Показов 3558. Ответов 47
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Как правильно написать приведение к типу &(PVOID&) через reinterpret_cast?
(в Detours вообще написано что DetourAttach ждет первым аргументом void**, но когда я привожу к void** вместо &(PVOID&) то оно крашит процесс при внедрении :/
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
21.08.2021, 03:27
Ответы с готовыми решениями:

Ошибка: multiple definition of `void std::swap<A>(A&amp;, A&amp;)
Хочу специализировать swap для своего класса. Получаю ошибку. Вот код:#ifndef A_H #define A_H ...

Язык C, напечатать таблицу истинности логической функции (A & B & C), где & - знаки логический операций И, НЕ
напечатать таблицу истинности логической функции (A &amp; B &amp; C), где &amp; - знаки логический операций И,...

Почему friend ostrem& operator <<(ostream& outs, const Rational&); - invalid function declaration?
Пытаюсь скомпилировать программу пишет friend ostrem&amp; operator &lt;&lt;(ostream&amp; outs, const...

В заштрихованную фигуру бросают точки с координатами x и y. Получить координаты первой точки не попавшей в эту область (фигура x*x+y*y<25&&x*x+y*y>=9&
В заштрихованную фигуру бросают точки с координатами x и y. Получить координаты первой точки не...

47
2837 / 2339 / 708
Регистрация: 29.06.2020
Сообщений: 8,655
21.08.2021, 19:45 21
Author24 — интернет-сервис помощи студентам
два вызова
C++
1
test(&(reinterpret_cast<PVOID>(TrueSleep)));
и
C++
1
2
PVOID lpvoid= reinterpret_cast<PVOID>(TrueSleep);  // так же как и ты выше в своем коде,
test(&lpvoid); // уже все ок
идентичны ? но первый не работает.

так что не убежден
Цитата Сообщение от DrOffset Посмотреть сообщение
Нет, все именно так. Никто тут ничего не продлевает.
завтра со свжей головой буду разбираться, где собака.
0
18844 / 9843 / 2408
Регистрация: 30.01.2014
Сообщений: 17,286
21.08.2021, 19:51 22
Цитата Сообщение от SmallEvil Посмотреть сообщение
идентичны ?
С чего бы?
В первом у нас rvalue в результате каста.
А во втором у нас выражение lpvoid - это lvalue.

Добавлено через 3 минуты
Цитата Сообщение от SmallEvil Посмотреть сообщение
так что не убежден
Ссылка что-то может продлить только до конца блока, либо до конца полного выражения.
Так что вам достаточно немного подумать, что даже если бы это произошло, то "продленный" объект просто помер бы в конце выражения и DetourAttach получил бы адрес дохлого объекта. Но этого не происходит.
Так что ни о каком продлении речь тут не идет. Речь только о реинтерпретации.
0
2837 / 2339 / 708
Регистрация: 29.06.2020
Сообщений: 8,655
21.08.2021, 20:02 23
Цитата Сообщение от DrOffset Посмотреть сообщение
В первом у нас rvalue в результате каста.
Так о чем я и говорю, указателя на указатель достаточно для изменения исходного указателя.
вот поэтому в реинтерперт каст в вызове функции и добавлена ссылка (ссылка на указатель), то есть из ссылки можно взять адресс, а из rvalue нет.

ладно, походу я совсем запутался, или меня запутали.
0
18844 / 9843 / 2408
Регистрация: 30.01.2014
Сообщений: 17,286
21.08.2021, 20:09 24
SmallEvil, да, и работа с "продленным" временным объектом (я пишу это не потому, что допускаю тут хоть малейшую возможность наличия тут этого явления, а для того, чтобы на ваших ошибочных рассуждениях вам было проще увидеть их ошибочность) противоречит тому, что задумано в этом коде. Нужно изменить именно TrueSleep.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
 
void Sleep(unsigned) {
    std::cout << "Original sleep\n";
}
 
static void (* TrueSleep)(unsigned) = Sleep;
 
static void AnotherSleep(unsigned) {
    std::cout << "Another sleep\n";
}
 
void test(void ** p)
{
    *p = reinterpret_cast<void*>(&AnotherSleep);
}
 
int main()
{
    TrueSleep(0);
    {
        test(&reinterpret_cast<void*&>(TrueSleep));
    }
    TrueSleep(0);    
}
https://rextester.com/AVCFI76003

А вариант с продлением, если бы он тут был возможен, работал бы так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
 
void Sleep(unsigned) {
    std::cout << "Original sleep\n";
}
 
static void (* TrueSleep)(unsigned) = Sleep;
 
static void AnotherSleep(unsigned) {
    std::cout << "Another sleep\n";
}
 
void test(void ** p)
{
    *p = reinterpret_cast<void*>(&AnotherSleep);
}
 
int main()
{
    TrueSleep(0);
    {
        void * tmpExtended = reinterpret_cast<void*>(TrueSleep);
        test(&tmpExtended);
    }
    TrueSleep(0);    
}
https://rextester.com/QQO44259

Добавлено через 47 секунд
Цитата Сообщение от SmallEvil Посмотреть сообщение
Так о чем я и говорю, указателя на указатель достаточно для изменения исходного указателя.
Нет, не достаточно.
Короче, см. выше примеры.
После него все должно быть понятно.

Добавлено через 39 секунд
Цитата Сообщение от SmallEvil Посмотреть сообщение
вот поэтому в реинтерперт каст в вызове функции и добавлена ссылка (ссылка на указатель), то есть из ссылки можно взять адресс, а из rvalue нет.
Это верно.
Но не потому что там что-то продлевается.
0
2837 / 2339 / 708
Регистрация: 29.06.2020
Сообщений: 8,655
21.08.2021, 20:23 25
Цитата Сообщение от DrOffset Посмотреть сообщение
Но не потому что там что-то продлевается.
да, не потому, а потому что после каста из ссылкой, выходит другой тип чем каст из PVOID, вот в этом мне и стоит разобраться (поэксперементировать). Спасибо за терпимость и понимание.

То есть, каст со ссылкой не является rvaluе.
Только вчера начал читать Мейерса и первая глава там об этом .

Добавлено через 37 секунд
Цитата Сообщение от DrOffset Посмотреть сообщение
Нет, не достаточно.
достаточно
0
18844 / 9843 / 2408
Регистрация: 30.01.2014
Сообщений: 17,286
21.08.2021, 20:27 26
Цитата Сообщение от SmallEvil Посмотреть сообщение
достаточно
Я имел в виду,что вот такого
Цитата Сообщение от eXpl01TeR Посмотреть сообщение
привожу к void** вместо &(PVOID&) то оно крашит процесс при внедрении :/
недостаточно.
0
2837 / 2339 / 708
Регистрация: 29.06.2020
Сообщений: 8,655
21.08.2021, 20:34 27
вот не ожидал что с реинтерперт каст будут камни подводные ...
0
18844 / 9843 / 2408
Регистрация: 30.01.2014
Сообщений: 17,286
21.08.2021, 20:49 28
Цитата Сообщение от SmallEvil Посмотреть сообщение
а потому что после каста из ссылкой, выходит другой тип чем каст из PVOID
Так я об этом и говорил.
Цитата Сообщение от DrOffset Посмотреть сообщение
Ссылка тут дает возможно работать непосредственно с объектом TrueSleep (а не с временным объектом) в результате каста.
Каст интерпретировал тип TrueSleep другим образом, но ссылка дала возможно применить эту интерпретацию непосредственно к объекту TrueSleep (т.е. сослаться на него, но под видом другого типа).

Не понятно тогда чего вы решили, что
Цитата Сообщение от SmallEvil Посмотреть сообщение
кажется тут немного не так
Если же мы просто скастим TrueSleep к void**, как это сделал ТС, то мы не добьемся такого же эффекта. Мы просто получим значение исходного указателя на функцию в качестве указателя на указатель. В то время как нам нужно получить адрес исходного указателя на функцию.

Добавлено через 10 минут
Цитата Сообщение от SmallEvil Посмотреть сообщение
вот не ожидал что с реинтерперт каст будут камни подводные ...
Тут вроде бы все на поверхности. Просто не нужно заниматься делами без понимания того что за ними стоит.

Мы, грубо говоря, открываем электрический щиток и начинаем тыкать без разбора во все цепи отверткой (электрик внеше же так же делал), а когда получаем короткое замыкание - чешем репу и говорим "вот уж не ожидал, что со щитком такие подводные камни". Это звучит очень глупо, когда экстраполируется на реальную жизнь, а в программировании запросто может быть
Цитата Сообщение от eXpl01TeR Посмотреть сообщение
Я её сам не понимаю, но везде в примерах перехвата через Microsoft Detours пишут именно через &(PVOID&)
Добавлено через 4 минуты
Кстати, всегда своим новым сотрудникам говорю, что примеры в документации даются не для переписывания в ваш код, а для того чтобы вы разобрались в принципах работы.
0
2837 / 2339 / 708
Регистрация: 29.06.2020
Сообщений: 8,655
21.08.2021, 21:02 29
Пример со щитком так себе, как и любые другие аналогии, которые я не люблю, в щитке все ясно, и все выглядит тем чем есть, не так как с++...
0
18844 / 9843 / 2408
Регистрация: 30.01.2014
Сообщений: 17,286
21.08.2021, 21:02 30
SmallEvil, для кого-то в щите выглядит "чем есть", а для условного ребенка не выглядит. Он запросто может так сделать. А для меня вся эта ситуация выглядит "чем есть". А для кого-то - это "магия", так же как для ребенка "магия" то, что делает электрик. Т.е. тут разница всего лишь в уровне предметной области. В электрощит вникнуть проще, чем в то, что делается в программировании, но по сути само "вникание" - это действие одной природы.

И на самом деле это не аналогия. Это демонстрация общего подхода, который можно описать коротко как "начать фигачить без понимания сути дела". Сама по себе деятельность не играет роли.
0
ablex
21.08.2021, 21:08
  #31

Не по теме:

Цитата Сообщение от SmallEvil Посмотреть сообщение
так себе, как и любые другие аналогии
Чувак, он не работу программиста с работой электрика сравнивает, а объясняет тупое обезъяничание в любой работе.
Нет тут никакой аналогии, речь все время об одном.

0
2837 / 2339 / 708
Регистрация: 29.06.2020
Сообщений: 8,655
21.08.2021, 21:09 32
Цитата Сообщение от DrOffset Посмотреть сообщение
"начать фигачить без понимания сути дела"
ну это не про меня (хотя по последним постам могло быть адресовано мне), и еще код по тому что достаточно указателя на указетель.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
void changePointer(void ** pp){
    int * pi = new int;
    *pi=111;
     *pp = reinterpret_cast<int *>(pi);
}
int main()
{
    int i = 101;
    int * pi = &i; // указтель на inr
    //changePointer(&reinterpret_cast<void*>(pi)); //  error: lvalue required as unary ‘&’ operand
                                                 //changePointer(&reinterpret_cast<void*>(pi));
    void * ppi =&pi;
    changePointer((void**)(&pi));
    std::cout<<*pi<<std::endl;
}
0
18844 / 9843 / 2408
Регистрация: 30.01.2014
Сообщений: 17,286
21.08.2021, 21:14 33
SmallEvil, этот код о том, что достаточно просто указателя, у которого возможно взять правильный адрес.
Такой же пример я выше показывал в #10

А слова о том, что достаточно void** я понял в контексте того, что описывал ТС в первом сообщении.
1
2837 / 2339 / 708
Регистрация: 29.06.2020
Сообщений: 8,655
21.08.2021, 21:18 34
но фишку с рентерпетркаст надо записывать отдельно , в большой блокнот
0
18844 / 9843 / 2408
Регистрация: 30.01.2014
Сообщений: 17,286
21.08.2021, 21:24 35
Цитата Сообщение от SmallEvil Посмотреть сообщение
еще код по тому что достаточно указателя на указетель.
Резюмируем, что ТС проще всего сделать так:
C++
1
reinterpret_cast<PVOID*>(&TrueSleep);
Сначала получим адрес указателя на функцию, а потом интерпретируем его как PVOID*, это наиболее простой для понимания способ.
А вот зачем в примерах MS они делали не так (PVOID*)(&TrueSleep), а так &(PVOID&)(TrueSleep) - непонятно. Никакой практической ценности именно в таком подходе здесь нет.
Эта ситуация еще раз красноречиво намекает на то, что переписывать примеры к себе в код - не надо.
1
2837 / 2339 / 708
Регистрация: 29.06.2020
Сообщений: 8,655
21.08.2021, 21:31 36
Цитата Сообщение от DrOffset Посмотреть сообщение
reinterpret_cast<PVOID*>(&TrueSleep);
мне уже сложно искать правильный ответ, его нужно искать сначала,
но такое не пройдет !

Добавлено через 1 минуту
ибо, шаблонная функция - реинтерпреткаст с простым указателем даст рвалую

Добавлено через 26 секунд
а с ссылкой даст ссылку
0
18844 / 9843 / 2408
Регистрация: 30.01.2014
Сообщений: 17,286
21.08.2021, 21:39 37
Цитата Сообщение от SmallEvil Посмотреть сообщение
но такое не пройдет !
Все пройдет.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <windows.h>
#include <detours.h>
 
static LONG dwSlept = 0;
 
// Target pointer for the uninstrumented Sleep API.
//
static VOID (WINAPI * TrueSleep)(DWORD dwMilliseconds) = Sleep;
 
// Detour function that replaces the Sleep API.
//
VOID WINAPI TimedSleep(DWORD dwMilliseconds)
{
    // Save the before and after times around calling the Sleep API.
    DWORD dwBeg = GetTickCount();
    TrueSleep(dwMilliseconds);
    DWORD dwEnd = GetTickCount();
 
    InterlockedExchangeAdd(&dwSlept, dwEnd - dwBeg);
}
 
// DllMain function attaches and detaches the TimedSleep detour to the
// Sleep target function.  The Sleep target function is referred to
// through the TrueSleep target pointer.
//
BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved)
{
    if (DetourIsHelperProcess()) {
        return TRUE;
    }
 
    if (dwReason == DLL_PROCESS_ATTACH) {
        DetourRestoreAfterWith();
 
        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());
        DetourAttach(reinterpret_cast<PVOID*>(&TrueSleep), TimedSleep);
        DetourTransactionCommit();
    } else if (dwReason == DLL_PROCESS_DETACH) {
        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());
        DetourDetach(reinterpret_cast<PVOID*>(&TrueSleep), TimedSleep);
        DetourTransactionCommit();
    }
    return TRUE;
}
Цитата Сообщение от SmallEvil Посмотреть сообщение
ибо, шаблонная функция - реинтерпреткаст с простым указателем даст рвалую
При чем тут шаблон?
В любом случае это не помешает.

Добавлено через 2 минуты
....
Цитата Сообщение от SmallEvil Посмотреть сообщение
но такое не пройдет !
Цитата Сообщение от SmallEvil Посмотреть сообщение
C++
1
changePointer((void**)(&pi));
Удивительно как вы умудрились противоречить сами себе.
Вы только что предложили самое лучшее для ТС решение его вопроса, и даже продемонстрировали его кодом, но стоило мне вас поддержать, так вы сразу же бросились со мной спорить. Это как так?
0
155 / 9 / 1
Регистрация: 14.08.2019
Сообщений: 768
21.08.2021, 21:41  [ТС] 38
Цитата Сообщение от DrOffset Посмотреть сообщение
Резюмируем, что ТС проще всего сделать так:
C++
1
reinterpret_cast<PVOID*>(&TrueSleep);
Забавно, вчера я именно так и сделал, но подумал что это как-то слишком просто и что я явно где-то ошибся)

Так лучше делать
C++
1
DetourAttach(&reinterpret_cast<PVOID&>(pFunc), myFunc);
или
C++
1
DetourAttach(reinterpret_cast<PVOID*>(&pFunc), myFunc);
В чем отличие?
0
18844 / 9843 / 2408
Регистрация: 30.01.2014
Сообщений: 17,286
21.08.2021, 21:43 39
Цитата Сообщение от eXpl01TeR Посмотреть сообщение
В чем отличие?
Все отличия описаны выше. Я второй раз так распинаться не буду

Добавлено через 45 секунд
Цитата Сообщение от eXpl01TeR Посмотреть сообщение
Так лучше делать
Второй вариант понятнее, на мой взгляд. Требует меньше знаний для использования.
1
2837 / 2339 / 708
Регистрация: 29.06.2020
Сообщений: 8,655
21.08.2021, 21:47 40
Цитата Сообщение от DrOffset Посмотреть сообщение
Это как так?
нет это не так, я просто реально заблудился ) сорри
0
21.08.2021, 21:47
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
21.08.2021, 21:47
Помогаю со студенческими работами здесь

ostream &operator<< (ostream &output, const Array &obj) - что означает эта строка?
void Array::getArray() // вывод массива { for (int ix = 0; ix &lt; size; ix++) cout &lt;&lt;...

Нюансы синтаксиса: где, как и для чего используется &&
Когда применяется ссылка на ссылку? В STL есть классы, конструкторы которых принимают ссылку на...

Как проверить, принадлежит ли символ заданному диапазону m...n, кроме if (c <= n && c >= m) ?
есть какая-нибудь более короткая запись для проверки, принадлежит ли символ заданному диапазону...

Порядок вычисления: операторы «|» и «||», «&» и «&&»
В Java булевые операторы «|» и «||», и «&amp;» и «&amp;&amp;» отличаются друг от друга порядком вычеслений, а в...

Как заменить if(a > first && a < second) одним оператором?
Как изменить if(a &gt; first &amp;&amp; a &lt; second) что бы введенное значение входило в заданные поля...

Friend ostream& operator<<(ostream& stream, CArr& obj);
CArr.h #pragma once class CArr{ int* arr = nullptr; int size = 10; void swap(int *a, int...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru