Открываете аргументы принимаемые WriteProcessMemory и смотрим: 1. дескриптор процесса, его валидность проверяется при получении. 2. Дальше адрес куда записывать 3. Дальше адрес откуда читать 4. Кол-во данных которые необходимо записать 5. Опциональные параметры, сколько удалось записать.
Все эти пункты, тот кто использует API должен сам проверять, мы чётко обозначаем какие данные нам нужны на вход и предупреждаем, что защиты от дурака нет, если она им нужна пусть сделают сами.
Если вы уж так хотите защиту от дурака, просто добавляет пару if, и возвращение bool переменной или HRESULT, кому как нравится.
Если функция выполнилась успешно, возвращает true .
А если вдруг false, то достаточно вызвать GetLastError , если ошибка в переданных данных в функцию. А если ошибка была обнаружена нашей защитой, то логирование. Либо уже вместо bool , возвращает некое значение.
Самое интересное в том, что валидность дескриптора проверяется сугубо при его получении, сама функция возвращает HRESULT, по которому и смотрят.
Дальше, как вы собрались проверять адрес куда записывать? nullptr по сути является 0. И в теории при спец. задачах, по нему можно записать и считать. А ваша защита от дурака не даст, ведь она посчитает что это nullptr.
С адресом откуда читать, ситуация та же.
Ну разве что кол-во данных.. будет странно что оно равно нулю, хотя мало ли какая там логика у программы, извращения бывают самые разные.
И здесь внимание:
НАША API НЕ ДОЛЖНА СВЯЗЫВАТЬ РУКИ. Не нужно из-за своего скудомия делать по вашему мнению "Обработчик не верных данных". Потому что они могут быть вполне верными, просто очень специфичными.
Надеюсь читающий данный текст обладает интеллектом и не поставит минус
DLC, которые так и не вышли, обещание детального мира - ну, короче, дефолтная лапша.
В той же одиночной GTA 5 делать вообще нечего - пресные сюжетные задания (не все) - и всё.
Если верить заявлениям, карта GTA 6 - 125 кв. км, а в пятой части было около 50. Но если найти изображение карты (если, конечно, это правда), то даже эмпирическим путём ясно, что вся эта масштабность - это куча лесов.
Но вот что на данный момент: они (Rockstar) выпускают новую часть, когда в прошлой достаточно багов, а онлайн-режим - это один сплошной баг и долгие загрузки миссий. Радует, что RTX прикрутили.
Но если, например, опираться на RDR 2, в которой разработчики делают механику изменения яичек жеребца в зависимости от температуры, разложения трупов, но в самой игре геймплея просто нет - задания в духе "принеси-подай". То есть есть шанс, что GTA 6 будет такой же - да, будут разные механики животных и т. п. Но возникает вопрос: а что делать в игре?
И это я говорю как человек, который переиграл во все продукты Rockstar. Для меня игры - это способ получить ту роль, которую в жизни я не получу (да и не хочу), а не ползать и карточки собирать, и тому подобное. Это не геймплей, это дебилизм - собирать 50 условных карточек ради доступа к текстурке.
Вот два последних продукта Rockstar - GTA 5 и RDR 2. В них буквально нет геймплея - уберите сюжетку, и всё. Ну что делать? В RDR 2 охота поначалу прикольная, но потом быстро надоедает. Так что думаю, и GTA 6 будет такой же, потому что у Rockstar такое видение и план (без него нельзя создать такие продукты). На это указывает то, что я описал выше
У Рокстар древняя тактика - обещать, а потом на выходе всё другое. Собственно о игре ничего не известно, а фанатики верят всему подряд. Будет по итогу как с гта 5
Вдумайтесь в то что делает Borrow Checker и поймёт при чём тут "Сборщик мусора", мусор, в нашем случае это то, что не корректно работает с памятью, ну а сборщик, это тот алгоритм что собирает такой код, и показывает нам где это.
Получается сборщик мусора, и да, раз вы такой грамотный то RAII не сборщик мусора, это идея что бы в конструктор выделение памяти, а в деконструктор её освобождение
У WinAPI своя логика, подробная ошибка, вот что бы прям очень подробно, получаем через GetLastError, а так возвращение BOOL указывает на то успешно завершилась функция или нет.
Если не успешно, то дёргаем GetLastError , но это вообще не С++, а библиотека на нём
Так, если в языке что-то возможно, это добавили по самым разным причинам, в первую очередь, гибкость.
Если вы или ещё кто-то, психически болен, и начинает усложнять конструкты, то кто вам виноват?
Попробуйте на языке ПРОГРАММИРОВАТЬ, а не искать извращённые способы чтобы потом кидаться ними в комментариях.
А единственный явный плюс у RUST, который выделяют это Borrow Checker . Ну то есть снова кто-то не осилил указатели и пошёл писать очередной сборщик мусора, но продвинутый.
То есть вся слава языка просто из-за этого.
Ну то есть были те, кто не смогли запомнить простое правило, написал new, напиши delete , или calloc/malloc, напиши free
А теперь самое интересное, внешние библиотеки ваша фича не проверяет, интересно сколько времени уйдёт у майкрософт на переписывание DirectX с плюсов на RUST ?
Я сейчас про то, где вы нашли этот кусок кода, я просматривал куча проектов на плюсах, сам пишу, ни кто так, никогда не пишет, а встретить тип auto это чудо, а подобный конструкт тем более.
Все всегда пишут:
int foo() { int i = 1; return 1; }
И так всегда и во всём, в том числе в коде от майкрософт.
Не нужно думать раз язык что-то позволяет, то ним так и пользуются
Ладно пойдём от обратного, примитивно, означает что всё прозрачно и понятно, "Если вам нужно сделать шаг вперёд, вы просто его делаете, вам не нужно делать кульбит", С++ как раз про это, он даёт решение многих действий , и эту же философию продолжают те кто разрабатывают на нём. Вот функция читает с файла, если не смогла прочитать, возвращает код ошибки, она не пытается сама завершить весь процесс и т.п.
Кстати единственно что не нравится это отсутствие типа данных для HEX чисел, приходится через указатель, но в RUST его тоже нет.
Вот сама идея функции: данные из вне могут быть, а могут и нет, выполняет некий код, и есть возможность вывода данных. Всё. Больше ни каких прикруток не нужных. Проще уже не сделать, а попытки псевдо-оптимизации путём прикручивания каких-то там состояний после выполнения функций, зачастую делают только хуже.
Вот про это были Си, и теперь же С++, упростить это нельзя.
И вот отсюда и простая реализация, указываешь есть ли данные на выходе, название функции и перечисление аргументов функции их тип и название. ВСЁ. Что вы туда запихнуть пытаетесь? Если ничего, так зачем порождать миллион языков, которые что то там пытаются?
Ну да, если простая обёртка выглядит криво, то функция со сложной логикой точно будет хорошо.
Гениально.
"Во-вторых, ясное дело, что если вы будете вызывать из языка, где принято использовать другие, не Си-подобные приёмы, тонкую обёртку над сишной функцией, у вас будет некрасивый обвязочный код."
"Во-вторых, ясное дело, что если вы будете вызывать из языка"
что вызывать то?
"где принято использовать другие, не Си-подобные приёмы"
А почему? Си-язык, возник для удобств, что бы на ассемблере не строчить, и ни кто после ассемблерных мнемоник не хотел перегружать язык кучей лишних символов. То есть си-стайл уже сам по себе имеет девиз "Просто и логично" , но нет надо ведь всё испортить
"тонкую обёртку над сишной функцией, у вас будет некрасивый обвязочный код"
Ну да, конфета плохая не из-за производства, а из-за фантика, я вас понял.
Это я повторно ответил, потому что вы теперь отпираетесь и говорите что я вас не так понял.
Некрасивый обвязочный код, сугубо из-за того что сам язык такой
"Во-вторых, ясное дело, что если вы будете вызывать из языка, где принято использовать другие, не Си-подобные приёмы, тонкую обёртку над сишной функцией, у вас будет некрасивый обвязочный код."
Ну то есть, вы буквально говорите, что если не си-подобный приём, то будет не красиво.
ДА ПРИ ЧЁМ ТУТ ПАМЯТЬ, ЧТО ВЫ К НЕЙ ПРИСТАЛИ, ЭТО ПРОСТО КАК ПРИМЕР.
Вот сразу видно любителей Rust и т.п. У них проблемы с логикой, тут не важно что делает функция которую обернули, это просто пример.
Вам нужно объяснять? Или вы проведёте сравнение и увидите простоту и лёгкость С++ в базовой задаче?
Вы действительно считаете что RUST выглядит и есть лучше чем C++ ?
P.s. На меня накинулись фанаты Rust, у которых от их языка уже проблемы с логикой, так как они не понимают что тут слова про память просто пример, а не аргумент
static_cast - Преобразование указателей/ссылок в иерархии наследования вверх (к базовому классу) и вниз (к производному), но без проверок во время выполнения (вы должны быть уверены в типе сами). Вызов явных конструкторов или операторов преобразования.
dynamic_cast - Безопасное преобразование во время выполнения. Единственный каст, который работает во время выполнения программы. Если преобразовать указатель не получится - вернет nullptr. Если преобразовать ссылку не получится - выбросит исключение std::bad_cast. Работает только с полиморфными классами (у которых есть хотя бы одна virtual функция, обычно деструктор).
const_cast - Единственный каст, который умеет убирать (или добавлять) модификаторы const и volatile. Например, когда вы вызываете старую C-функцию, которая принимает char* (неконстантный), но вы уверены, что эта функция не будет менять данные, а у вас есть только const char*.
reinterpret_cast - Переинтерпретировать (прочитать заново) биты одного типа как биты другого типа. Компилятор просто берет адрес и считает его адресом другого типа, не генерируя никакого машинного кода для преобразования.
bit_cast - Появился в C++20 как альтернатива опасному reinterpret_cast. Он не переинтерпретирует указатели, а создает НОВЫЙ объект, полностью копируя биты старого в новый.
Зачем вы, не желая даже 5 минут погуглить, лезет со своим Rust? При чём тут он? Здесь другой язык, с более чем понятной и удобной логикой
В стандарте C++ четко сказано: "Переменная вводится в программу объявлением (declaration) и имеет идентификатор (имя)".
это когда же у нас вызов функции и передача аргумента вдруг стало причиной инициализации переменной?
Конечно иногда аргументы функции передаются через стек, но в основном через регистры, и из-за этого считать что аргумент это вдруг отдельная переменная - как минимум странно. Да, конечно если рассматривать передачу через стек, то механизм схож с локальной переменной, но это всё равно другое. Ни разу не слышал, чтобы хоть кто-то из тех же реверс-инженеров говорил что аргумент функции это переменная.
struct S { int x = 5; int y{10}; S() : y{2}, x(1) {} };
ВОТ ЭТО, ни как не переменная, сама структура (её описание) - это тип данных (чертеж), а переменная - это экземпляр (конкретный объект в памяти).
return x; return {1, 2, 3}; throw x;
И это вообще и близко, тоже не переменные.
"Простые вещи просто не делаются"
Ну оберни в функцию и будет тебе всё по одной кнопке? За чем своё субъективное ощущение после условного питона(или джавы), выдавать за некую справедливую оценку языка?
"Проблемы кастинга"
Тут автор буквально пишет, что после джавы, ему тяжело запомнить приведение типов к другим типам и так же показывает, что читать в интернете зачем нужен каждый он не хочет, а зря, узнал бы зачем они нужны.
Короче дальше мне стало нудно читать ибо:
1. Автор выдаёт субъективное ощущение за объективное оценивание
2.Автор так же явно начал трогать С++, после более высокоуровневого языка (той же джавы которую он активно упоминает, что много даёт понять) , при этом открывать документацию или какие-то статьи он не хочет, возможно где-то пробежался, нахватался и теперь ноет на хабре.
Открываете аргументы принимаемые WriteProcessMemory и смотрим:
1. дескриптор процесса, его валидность проверяется при получении.
2. Дальше адрес куда записывать
3. Дальше адрес откуда читать
4. Кол-во данных которые необходимо записать
5. Опциональные параметры, сколько удалось записать.
Все эти пункты, тот кто использует API должен сам проверять, мы чётко обозначаем какие данные нам нужны на вход и предупреждаем, что защиты от дурака нет, если она им нужна пусть сделают сами.
Если вы уж так хотите защиту от дурака, просто добавляет пару if, и возвращение bool переменной или HRESULT, кому как нравится.
Если функция выполнилась успешно, возвращает true .
А если вдруг false, то достаточно вызвать GetLastError , если ошибка в переданных данных в функцию. А если ошибка была обнаружена нашей защитой, то логирование. Либо уже вместо bool , возвращает некое значение.
Самое интересное в том, что валидность дескриптора проверяется сугубо при его получении, сама функция возвращает HRESULT, по которому и смотрят.
Дальше, как вы собрались проверять адрес куда записывать? nullptr по сути является 0. И в теории при спец. задачах, по нему можно записать и считать. А ваша защита от дурака не даст, ведь она посчитает что это nullptr.
С адресом откуда читать, ситуация та же.
Ну разве что кол-во данных.. будет странно что оно равно нулю, хотя мало ли какая там логика у программы, извращения бывают самые разные.
И здесь внимание:
НАША API НЕ ДОЛЖНА СВЯЗЫВАТЬ РУКИ. Не нужно из-за своего скудомия делать по вашему мнению "Обработчик не верных данных". Потому что они могут быть вполне верными, просто очень специфичными.
Надеюсь читающий данный текст обладает интеллектом и не поставит минус
DLC, которые так и не вышли, обещание детального мира - ну, короче, дефолтная лапша.
В той же одиночной GTA 5 делать вообще нечего - пресные сюжетные задания (не все) - и всё.
Если верить заявлениям, карта GTA 6 - 125 кв. км, а в пятой части было около 50. Но если найти изображение карты (если, конечно, это правда), то даже эмпирическим путём ясно, что вся эта масштабность - это куча лесов.
Но вот что на данный момент: они (Rockstar) выпускают новую часть, когда в прошлой достаточно багов, а онлайн-режим - это один сплошной баг и долгие загрузки миссий. Радует, что RTX прикрутили.
Но если, например, опираться на RDR 2, в которой разработчики делают механику изменения яичек жеребца в зависимости от температуры, разложения трупов, но в самой игре геймплея просто нет - задания в духе "принеси-подай". То есть есть шанс, что GTA 6 будет такой же - да, будут разные механики животных и т. п. Но возникает вопрос: а что делать в игре?
И это я говорю как человек, который переиграл во все продукты Rockstar. Для меня игры - это способ получить ту роль, которую в жизни я не получу (да и не хочу), а не ползать и карточки собирать, и тому подобное. Это не геймплей, это дебилизм - собирать 50 условных карточек ради доступа к текстурке.
Вот два последних продукта Rockstar - GTA 5 и RDR 2. В них буквально нет геймплея - уберите сюжетку, и всё. Ну что делать? В RDR 2 охота поначалу прикольная, но потом быстро надоедает. Так что думаю, и GTA 6 будет такой же, потому что у Rockstar такое видение и план (без него нельзя создать такие продукты). На это указывает то, что я описал выше
У Рокстар древняя тактика - обещать, а потом на выходе всё другое. Собственно о игре ничего не известно, а фанатики верят всему подряд. Будет по итогу как с гта 5
А зачем для этого гитхаб :D На болванку и так можно записать
Контролирование включает в себя в том числе и ограничение доступа к интернету
"назад никто бы и подумать не мог", так большинство не увидит даже если их тыкать в это, ещё начнёт высмеивать.
Знаю некоторых персон кто говорил людям в промежутке между 10 и 14, что интернет ваш начнут контролировать.
Ну это и так понятно, такой пласт общения людей и т.п. Как не захватить такое
Если подозрение что это не просто спаммер, а настоящий ИИ-агент :D
Ну надо ведь юмор уметь понимать.
Вдумайтесь в то что делает Borrow Checker и поймёт при чём тут "Сборщик мусора", мусор, в нашем случае это то, что не корректно работает с памятью, ну а сборщик, это тот алгоритм что собирает такой код, и показывает нам где это.
Получается сборщик мусора, и да, раз вы такой грамотный то RAII не сборщик мусора, это идея что бы в конструктор выделение памяти, а в деконструктор её освобождение
У WinAPI своя логика, подробная ошибка, вот что бы прям очень подробно, получаем через GetLastError, а так возвращение BOOL указывает на то успешно завершилась функция или нет.
Если не успешно, то дёргаем GetLastError , но это вообще не С++, а библиотека на нём
Так, если в языке что-то возможно, это добавили по самым разным причинам, в первую очередь, гибкость.
Если вы или ещё кто-то, психически болен, и начинает усложнять конструкты, то кто вам виноват?
Попробуйте на языке ПРОГРАММИРОВАТЬ, а не искать извращённые способы чтобы потом кидаться ними в комментариях.
А единственный явный плюс у RUST, который выделяют это Borrow Checker . Ну то есть снова кто-то не осилил указатели и пошёл писать очередной сборщик мусора, но продвинутый.
То есть вся слава языка просто из-за этого.
Ну то есть были те, кто не смогли запомнить простое правило, написал new, напиши delete , или calloc/malloc, напиши free
А теперь самое интересное, внешние библиотеки ваша фича не проверяет, интересно сколько времени уйдёт у майкрософт на переписывание DirectX с плюсов на RUST ?
Я сейчас про то, где вы нашли этот кусок кода, я просматривал куча проектов на плюсах, сам пишу, ни кто так, никогда не пишет, а встретить тип auto это чудо, а подобный конструкт тем более.
Все всегда пишут:
int foo() {
int i = 1;
return 1;
}
И так всегда и во всём, в том числе в коде от майкрософт.
Не нужно думать раз язык что-то позволяет, то ним так и пользуются
decltype(auto) foo() {
int i = 1;
return (i);
}
Вы где такое увидели вообще?
Неплохо конечно автор развёл всех на холивар :DDD
Ладно пойдём от обратного, примитивно, означает что всё прозрачно и понятно, "Если вам нужно сделать шаг вперёд, вы просто его делаете, вам не нужно делать кульбит", С++ как раз про это, он даёт решение многих действий , и эту же философию продолжают те кто разрабатывают на нём. Вот функция читает с файла, если не смогла прочитать, возвращает код ошибки, она не пытается сама завершить весь процесс и т.п.
Кстати единственно что не нравится это отсутствие типа данных для HEX чисел, приходится через указатель, но в RUST его тоже нет.
Вот сама идея функции: данные из вне могут быть, а могут и нет, выполняет некий код, и есть возможность вывода данных. Всё. Больше ни каких прикруток не нужных. Проще уже не сделать, а попытки псевдо-оптимизации путём прикручивания каких-то там состояний после выполнения функций, зачастую делают только хуже.
Вот про это были Си, и теперь же С++, упростить это нельзя.
И вот отсюда и простая реализация, указываешь есть ли данные на выходе, название функции и перечисление аргументов функции их тип и название. ВСЁ. Что вы туда запихнуть пытаетесь? Если ничего, так зачем порождать миллион языков, которые что то там пытаются?
Ну да, если простая обёртка выглядит криво, то функция со сложной логикой точно будет хорошо.
Гениально.
"Во-вторых, ясное дело, что если вы будете вызывать из языка, где принято использовать другие, не Си-подобные приёмы, тонкую обёртку над сишной функцией, у вас будет некрасивый обвязочный код."
"Во-вторых, ясное дело, что если вы будете вызывать из языка"
что вызывать то?
"где принято использовать другие, не Си-подобные приёмы"
А почему? Си-язык, возник для удобств, что бы на ассемблере не строчить, и ни кто после ассемблерных мнемоник не хотел перегружать язык кучей лишних символов. То есть си-стайл уже сам по себе имеет девиз "Просто и логично" , но нет надо ведь всё испортить
"тонкую обёртку над сишной функцией, у вас будет некрасивый обвязочный код"
Ну да, конфета плохая не из-за производства, а из-за фантика, я вас понял.
Это я повторно ответил, потому что вы теперь отпираетесь и говорите что я вас не так понял.
Некрасивый обвязочный код, сугубо из-за того что сам язык такой
"Во-вторых, ясное дело, что если вы будете вызывать из языка, где принято использовать другие, не Си-подобные приёмы, тонкую обёртку над сишной функцией, у вас будет некрасивый обвязочный код."
Ну то есть, вы буквально говорите, что если не си-подобный приём, то будет не красиво.
ДА ПРИ ЧЁМ ТУТ ПАМЯТЬ, ЧТО ВЫ К НЕЙ ПРИСТАЛИ, ЭТО ПРОСТО КАК ПРИМЕР.
Вот сразу видно любителей Rust и т.п. У них проблемы с логикой, тут не важно что делает функция которую обернули, это просто пример.
Так в смысле, обёртка над функцией не базовая задача? Одно из самых частых это обёртка над функцией с некоторой логикой.
Я показал пример обёртки над функцией, можно даже не знать что она делает(функция).
Смысл в том, что в С++ всё красиво и аккуратно, не каких лишних букв и символ.
Вот зачем отделять тип и словесный ид двоеточием, что это за порнография?
А вот что это за порнография ??
Ну как минимум потому что Rust выглядит как очередная кривая обёртка над С++.
Вот две функции для записи в память другого процесса:
RUST:
C++:
Вам нужно объяснять? Или вы проведёте сравнение и увидите простоту и лёгкость С++ в базовой задаче?
Вы действительно считаете что RUST выглядит и есть лучше чем C++ ?
P.s. На меня накинулись фанаты Rust, у которых от их языка уже проблемы с логикой, так как они не понимают что тут слова про память просто пример, а не аргумент
static_cast - Преобразование указателей/ссылок в иерархии наследования вверх (к базовому классу) и вниз (к производному), но без проверок во время выполнения (вы должны быть уверены в типе сами). Вызов явных конструкторов или операторов преобразования.
dynamic_cast - Безопасное преобразование во время выполнения. Единственный каст, который работает во время выполнения программы. Если преобразовать указатель не получится - вернет nullptr. Если преобразовать ссылку не получится - выбросит исключение std::bad_cast. Работает только с полиморфными классами (у которых есть хотя бы одна virtual функция, обычно деструктор).
const_cast - Единственный каст, который умеет убирать (или добавлять) модификаторы const и volatile. Например, когда вы вызываете старую C-функцию, которая принимает char* (неконстантный), но вы уверены, что эта функция не будет менять данные, а у вас есть только const char*.
reinterpret_cast - Переинтерпретировать (прочитать заново) биты одного типа как биты другого типа. Компилятор просто берет адрес и считает его адресом другого типа, не генерируя никакого машинного кода для преобразования.
bit_cast - Появился в C++20 как альтернатива опасному reinterpret_cast. Он не переинтерпретирует указатели, а создает НОВЫЙ объект, полностью копируя биты старого в новый.
Зачем вы, не желая даже 5 минут погуглить, лезет со своим Rust? При чём тут он? Здесь другой язык, с более чем понятной и удобной логикой
В стандарте C++ четко сказано: "Переменная вводится в программу объявлением (declaration) и имеет идентификатор (имя)".
это когда же у нас вызов функции и передача аргумента вдруг стало причиной инициализации переменной?
Конечно иногда аргументы функции передаются через стек, но в основном через регистры, и из-за этого считать что аргумент это вдруг отдельная переменная - как минимум странно. Да, конечно если рассматривать передачу через стек, то механизм схож с локальной переменной, но это всё равно другое. Ни разу не слышал, чтобы хоть кто-то из тех же реверс-инженеров говорил что аргумент функции это переменная.
struct S {
int x = 5;
int y{10};
S() : y{2}, x(1) {}
};
ВОТ ЭТО, ни как не переменная, сама структура (её описание) - это тип данных (чертеж), а переменная - это экземпляр (конкретный объект в памяти).
return x;
return {1, 2, 3};
throw x;
И это вообще и близко, тоже не переменные.
"Простые вещи просто не делаются"
Ну оберни в функцию и будет тебе всё по одной кнопке? За чем своё субъективное ощущение после условного питона(или джавы), выдавать за некую справедливую оценку языка?
"Проблемы кастинга"
Тут автор буквально пишет, что после джавы, ему тяжело запомнить приведение типов к другим типам и так же показывает, что читать в интернете зачем нужен каждый он не хочет, а зря, узнал бы зачем они нужны.
Короче дальше мне стало нудно читать ибо:
1. Автор выдаёт субъективное ощущение за объективное оценивание
2.Автор так же явно начал трогать С++, после более высокоуровневого языка (той же джавы которую он активно упоминает, что много даёт понять) , при этом открывать документацию или какие-то статьи он не хочет, возможно где-то пробежался, нахватался и теперь ноет на хабре.