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

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

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

Как правильно написать приведение к типу &(PVOID&) через reinterpret_cast?
(в Detours вообще написано что DetourAttach ждет первым аргументом void**, но когда я привожу к void** вместо &(PVOID&) то оно крашит процесс при внедрении :/
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
21.08.2021, 03:27
Ответы с готовыми решениями:

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

Язык 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 Rational&amp;); - invalid function declaration. ...

47
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
21.08.2021, 19:45
два вызова
C++
1
test(&(reinterpret_cast<PVOID>(TrueSleep)));
и
C++
1
2
PVOID lpvoid= reinterpret_cast<PVOID>(TrueSleep);  // так же как и ты выше в своем коде,
test(&lpvoid); // уже все ок
идентичны ? но первый не работает.

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

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

ладно, походу я совсем запутался, или меня запутали.
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
21.08.2021, 20:09
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
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
21.08.2021, 20:23
Цитата Сообщение от DrOffset Посмотреть сообщение
Но не потому что там что-то продлевается.
да, не потому, а потому что после каста из ссылкой, выходит другой тип чем каст из PVOID, вот в этом мне и стоит разобраться (поэксперементировать). Спасибо за терпимость и понимание.

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

Добавлено через 37 секунд
Цитата Сообщение от DrOffset Посмотреть сообщение
Нет, не достаточно.
достаточно
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
21.08.2021, 20:27
Цитата Сообщение от SmallEvil Посмотреть сообщение
достаточно
Я имел в виду,что вот такого
Цитата Сообщение от eXpl01TeR Посмотреть сообщение
привожу к void** вместо &(PVOID&) то оно крашит процесс при внедрении :/
недостаточно.
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
21.08.2021, 20:34
вот не ожидал что с реинтерперт каст будут камни подводные ...
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
21.08.2021, 20:49
Цитата Сообщение от SmallEvil Посмотреть сообщение
а потому что после каста из ссылкой, выходит другой тип чем каст из PVOID
Так я об этом и говорил.
Цитата Сообщение от DrOffset Посмотреть сообщение
Ссылка тут дает возможно работать непосредственно с объектом TrueSleep (а не с временным объектом) в результате каста.
Каст интерпретировал тип TrueSleep другим образом, но ссылка дала возможно применить эту интерпретацию непосредственно к объекту TrueSleep (т.е. сослаться на него, но под видом другого типа).

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

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

Мы, грубо говоря, открываем электрический щиток и начинаем тыкать без разбора во все цепи отверткой (электрик внеше же так же делал), а когда получаем короткое замыкание - чешем репу и говорим "вот уж не ожидал, что со щитком такие подводные камни". Это звучит очень глупо, когда экстраполируется на реальную жизнь, а в программировании запросто может быть
Цитата Сообщение от eXpl01TeR Посмотреть сообщение
Я её сам не понимаю, но везде в примерах перехвата через Microsoft Detours пишут именно через &(PVOID&)
Добавлено через 4 минуты
Кстати, всегда своим новым сотрудникам говорю, что примеры в документации даются не для переписывания в ваш код, а для того чтобы вы разобрались в принципах работы.
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
21.08.2021, 21:02
Пример со щитком так себе, как и любые другие аналогии, которые я не люблю, в щитке все ясно, и все выглядит тем чем есть, не так как с++...
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
21.08.2021, 21:02
SmallEvil, для кого-то в щите выглядит "чем есть", а для условного ребенка не выглядит. Он запросто может так сделать. А для меня вся эта ситуация выглядит "чем есть". А для кого-то - это "магия", так же как для ребенка "магия" то, что делает электрик. Т.е. тут разница всего лишь в уровне предметной области. В электрощит вникнуть проще, чем в то, что делается в программировании, но по сути само "вникание" - это действие одной природы.

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

Не по теме:

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

0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
21.08.2021, 21:09
Цитата Сообщение от 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
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
21.08.2021, 21:14
SmallEvil, этот код о том, что достаточно просто указателя, у которого возможно взять правильный адрес.
Такой же пример я выше показывал в #10

А слова о том, что достаточно void** я понял в контексте того, что описывал ТС в первом сообщении.
1
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
21.08.2021, 21:18
но фишку с рентерпетркаст надо записывать отдельно , в большой блокнот
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
21.08.2021, 21:24
Цитата Сообщение от SmallEvil Посмотреть сообщение
еще код по тому что достаточно указателя на указетель.
Резюмируем, что ТС проще всего сделать так:
C++
1
reinterpret_cast<PVOID*>(&TrueSleep);
Сначала получим адрес указателя на функцию, а потом интерпретируем его как PVOID*, это наиболее простой для понимания способ.
А вот зачем в примерах MS они делали не так (PVOID*)(&TrueSleep), а так &(PVOID&)(TrueSleep) - непонятно. Никакой практической ценности именно в таком подходе здесь нет.
Эта ситуация еще раз красноречиво намекает на то, что переписывать примеры к себе в код - не надо.
1
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
21.08.2021, 21:31
Цитата Сообщение от DrOffset Посмотреть сообщение
reinterpret_cast<PVOID*>(&TrueSleep);
мне уже сложно искать правильный ответ, его нужно искать сначала,
но такое не пройдет !

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

Добавлено через 26 секунд
а с ссылкой даст ссылку
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
21.08.2021, 21:39
Цитата Сообщение от 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 / 2
Регистрация: 14.08.2019
Сообщений: 771
21.08.2021, 21:41  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Резюмируем, что ТС проще всего сделать так:
C++
1
reinterpret_cast<PVOID*>(&TrueSleep);
Забавно, вчера я именно так и сделал, но подумал что это как-то слишком просто и что я явно где-то ошибся)

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

Добавлено через 45 секунд
Цитата Сообщение от eXpl01TeR Посмотреть сообщение
Так лучше делать
Второй вариант понятнее, на мой взгляд. Требует меньше знаний для использования.
1
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
21.08.2021, 21:47
Цитата Сообщение от DrOffset Посмотреть сообщение
Это как так?
нет это не так, я просто реально заблудился ) сорри
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
21.08.2021, 21:47

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

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Контроль уникальности строк в табличной части документа
Maks 18.06.2026
Алгоритм из решения ниже разработан на примере нетипового документа "ПланированиеСпецтехники" с табличной частью "НаличиеОборудования", разработанного в КА2. Задача: контроль уникальности строк в. . .
Клиент
Uhbif79 18.06.2026
Здесь простой клиент для работы с сервером.
Сервер
Uhbif79 18.06.2026
Выкладываю простейший сервер.
Дефенестрация
kumehtar 18.06.2026
Узнал интересное слово. Дефенестрация. Это когда ты выбрасываешь кого-либо или что-либо из окна. Возьму на вооружение)))
Дихотомия добра и зла
kumehtar 18.06.2026
Как Дзен-буддисты говорят о добре и зле: не нужно воевать против зла, нужно воевать против невежества. Тогда добро станет ествественным, и поэтому вечным. Но дело в том, что невежество всё время. . .
Своя Интернет-Компания
iceja 18.06.2026
Я программист с экономическим образованием, пишу свой проект, это SaaS для бизнесов. Мне нужен co-founder с высшим экономическим образованием, и/ или инвестор. Сейчас проект в интенсивной разработке,. . .
24 Мат модель здравосохранения: функциональные требования к строительству пищеблока
anaschu 18.06.2026
СРесурсами1: финансовый SD-контур, калькулятор функциональных требований пищеблока Сегодня разделили затраты в агенте Экономика по образцу модели НАСОСЫ, добавили расчёт ROI и построили первый. . .
23. что сделано за последнее время.
anaschu 17.06.2026
• Эталон: Клиника НИИ питания РАМН, Москва — централизованный пищеблок, 225 коек, 180 пациентов • Git: репозиторий med2, ветка абсентеизм. Рабочий файл: СРесурсами1_v4. alp • Смежный проект:. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru