Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.99/76: Рейтинг темы: голосов - 76, средняя оценка - 4.99
2 / 2 / 0
Регистрация: 31.10.2013
Сообщений: 17

Оперативная память и WinAPI (поиск строки в памяти процесса)

22.04.2015, 09:53. Показов 15522. Ответов 37
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравстуйте.
Работаю с оперативной памятью и WinApi. Пытаюсь найти строчку в памяти запущенного процесса.
Естественно не получается. Код скинул ниже.
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include <windows.h>
#include <iostream>
#include <psapi.h>//информация о памяти процесса
#include <fstream>//для вывода в документ адресов и значений по ним
using namespace std;
#pragma comment(lib, "psapi.lib")
 
//имя программы
#define PROGRAMM_NAME "jon@debian: ~"
 
 
//получить базовый адрес процесса
LPVOID GetBaseAddress(HANDLE hProc)
{
    //структура с информацией о процессе
    MODULEINFO miInfo;
 
    //получаем базовый адрес процесса
    if (GetModuleInformation(hProc, NULL, &miInfo, sizeof(miInfo)))
        return miInfo.EntryPoint;
    else
        return NULL;
}
 
//получить размер используемой памяти приложения(в байтах)
DWORD GetMemorySize(HANDLE hProc)
{
    //структура с информацией о процессе
    PROCESS_MEMORY_COUNTERS pmcInfo;
 
    //получаем информацию о процессе
    if (GetProcessMemoryInfo(hProc, &pmcInfo, sizeof(pmcInfo)))
        return (DWORD)pmcInfo.WorkingSetSize;
    else
        return 0;
}
 
 
void main()
{
    setlocale(LC_ALL, "Russian");//устанавливаем русский язык для вывода
 
    //ищем окно
    HWND hWnd = FindWindow(NULL, TEXT(PROGRAMM_NAME));
    if (!hWnd)
    {
        cout << "Программа не запущена.";
        return;
    }
 
    //получаем ID процесса
    DWORD dwPID;
    GetWindowThreadProcessId(hWnd, &dwPID);
    if (!dwPID)
    {
        cout << "Невозможно получить ID процесса.";
        return;
    }
 
    //получаем хэндл процесса
    HANDLE hProc;
    hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwPID);
    if (!hProc)
    {
        cout << "Невозможно получить хэндл процесса.";
        return;
    }
 
    //получаем начальный адрес процесса
    LPVOID dwStart = GetBaseAddress(hProc);
 
    //получаем размер занимаемой памяти
    DWORD dwMemSize = GetMemorySize(hProc);
    if (!dwMemSize)
    {
        cout << "Невозможно получить размер памяти, занимаемой приложением.";
        return;
    }
 
 
    cout << "Программа: "                    << PROGRAMM_NAME        << "\n"        <<
            "Handle Window: "                << hWnd                    << "\n"        <<
            "ProcessId: "                    << dwPID                << "\n"        <<
            "Handle Process: "                << hProc                << "\n"        <<
            "Начальный адрес: "                << dwStart                << "\n"        <<
            "Размер занимаемой памяти: "    << (dwMemSize / 1024)    << " кБ\n"    <<
            "\n\n\n\n";
 
    const char * signature = "192.168.56.101";      // Последовательность которую будем искать
    size_t len_signature = strlen (signature); // Длина последовательности.
    DWORD start = (DWORD)dwStart;//счётчик для цикла
    SIZE_T lpRead = 0;
 
    while(start < ((DWORD)dwStart + dwMemSize))
     {
        MEMORY_BASIC_INFORMATION mbi;
        
 
        int sz = VirtualQueryEx(hProc, (void *)start, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
 
        if(     (mbi.State == MEM_COMMIT)            //если регион в состоянии передачи памяти
                &&                                    //и
                (mbi.Protect != PAGE_READONLY)        //регион не только для чнения
                &&                                    //и
                (mbi.Protect != PAGE_EXECUTE_READ)    //регион не тролько с исполнением программного кода и чтением
                &&                                    //и
                (mbi.Protect != PAGE_GUARD)            //регион без сигнала доступа к странице
                &&                                    //и
                (mbi.Protect != PAGE_NOACCESS)        //регион не защищён доступом к нему
                )//то
        {
           
            if(mbi.RegionSize != lpRead)
            {
                BYTE* lpData = (BYTE*)malloc(mbi.RegionSize);//резервируем место для массива lpData, размером в регион
                
                if(ReadProcessMemory(hProc, (LPCVOID)start, lpData, mbi.RegionSize, &lpRead))
                {
                   cout << "Поиск в регионе размером " << mbi.RegionSize << " байт\n";//поиск строки в массиве
                
                      BYTE *p = lpData;
                      while((p = (BYTE*)memchr(p, signature[0], mbi.RegionSize - len_signature + 1 - (p - lpData))) != 0)
                      {
                         if ( 0 == memcmp(p+1, signature + 1, len_signature - 1))
                         {
                            // найдено!!! в (p) адрес нашего буфера, где обнаружена последовательность.
                            // соответственно адрес в приложении равен: Start + (p - lpData);
                             printf("%d\n",lpData);
                         }
                         ++p;
                      }
 
                }
            }
        }
 
        start += mbi.RegionSize;//переходим на следующий регион
    }
 
    cout << "\nГотово.";
 
    //закрываем хэндл процесса
    CloseHandle(hProc);
}
1
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
22.04.2015, 09:53
Ответы с готовыми решениями:

Поиск Строки в памяти процесса
Помогите нужно найти адресс по строке в процессе

Поиск строки в памяти другого процесса
привет доброго времени суток из едит.текст1 читал строку (как аррай ,тип FD CD 22 32 EE 33 этого) и показал его адрес в мемо1 (если их...

Поиск строки в памяти запущенного процесса и её изменение
Подскажи пожалуйста, что я делаю не так. Вот мой код. #include &quot;windows.h&quot; #include &lt;iostream&gt; using namespace std; int...

37
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
22.04.2015, 11:18
Цитата Сообщение от Кирилл Романов Посмотреть сообщение
Естественно не получается.
И естественно, что именно не получается и какие ошибки возникают,
написать ну никак нельзя.
0
2 / 2 / 0
Регистрация: 31.10.2013
Сообщений: 17
22.04.2015, 14:12  [ТС]
В том то и дело, что ошибок нет... По идеи должно работать...
0
 Аватар для jonson
240 / 213 / 84
Регистрация: 18.03.2010
Сообщений: 750
22.04.2015, 16:00
Цитата Сообщение от Кирилл Романов Посмотреть сообщение
Пытаюсь найти строчку в памяти запущенного процесса.
Приведенный код вообще способен найти хоть какую-то последовательность в памяти работающего процесса?
1
2 / 2 / 0
Регистрация: 31.10.2013
Сообщений: 17
22.04.2015, 17:45  [ТС]
Нет, хотелось бы узнать почему
0
46 / 31 / 12
Регистрация: 21.04.2015
Сообщений: 82
22.04.2015, 18:31
А вы уверены, что эта строка там есть? Прогнал ваш код под отладчиком - всё работает.
Или может быть строка там хранится в UNICODE?


В этом случае надо чуть-чуть изменить:
C++
1
2
3
4
const WCHAR * signature = L"192.168.56.101";      // Последовательность которую будем искать
size_t len_signature = lstrlenW(signature) * sizeof(WCHAR); // Длина последовательности.
 
if (0 == memcmp(p + sizeof(WCHAR), signature + 1, (len_signature - sizeof(WCHAR))))

Или может процесс запущен от имени администратора?
0
2 / 2 / 0
Регистрация: 31.10.2013
Сообщений: 17
22.04.2015, 20:07  [ТС]
Неа, не помогает... Я сам проходился под отладчиком, программа должна работать

Добавлено через 37 секунд
нет, никаких последовательностей не находит... я уже не знаю что и делать

Добавлено через 20 минут
А вы не работали с оперативной памятью? может у вас есть какой-нибудь пример для нахождения строк
0
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18031 / 7734 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
23.04.2015, 14:54
А искомая строка точно есть в памяти?
Может, она зашифрована, или еще не подгружена.
Пройдитесь сначала через Artmoney или CheatEngine.
0
2 / 2 / 0
Регистрация: 31.10.2013
Сообщений: 17
25.04.2015, 03:43  [ТС]
Спасибо, но именно данными программами проверяю результат. Строка там точно есть!
0
 Аватар для bananan
0 / 0 / 1
Регистрация: 25.04.2015
Сообщений: 1
25.04.2015, 11:00
попробуй воспользоваться функцией получения привилегий отладчика перед тем, как совершать любые манипуляции с памятью.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
BOOL DoRtlAdjustPrivilege(){
 
#define SE_DEBUG_PRIVILEGE 20L
#define AdjustCurrentProcess 0
    BOOL bPrev = FALSE;
    LONG(WINAPI *RtlAdjustPrivilege)(DWORD, BOOL, INT, PBOOL);
    *(FARPROC *)&RtlAdjustPrivilege = GetProcAddress(GetModuleHandle(L"ntdll.dll"), "RtlAdjustPrivilege");
    if (!RtlAdjustPrivilege) return FALSE;
    RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, AdjustCurrentProcess, &bPrev);
    return TRUE;
}
 
//......
int _tmain(int argc, _TCHAR* argv[])
 
{
/*** VARIABLES ***/
 
    if (!DoRtlAdjustPrivilege())  return 1;
    puts("Process opened sucessfully\nScanning memory...\n");
 
/*** YOUR CODE ***/
}
0
2 / 2 / 0
Регистрация: 31.10.2013
Сообщений: 17
25.04.2015, 12:03  [ТС]
Спасибо, но не помогает. Самое интересное, что строка точно есть в процессе, какие-то строки находит правильно, а какие-то нет
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
25.04.2015, 15:31
Лучший ответ Сообщение было отмечено Кирилл Романов как решение

Решение

Вы не там ищете:
C++
1
2
3
4
5
//получаем начальный адрес процесса
LPVOID dwStart = GetBaseAddress(hProc);
 
//получаем размер занимаемой памяти
DWORD dwMemSize = GetMemorySize(hProc);
Здесь идет поиск, начиная с EntryPoint исполняемого файла exe и далее,
размером всего с Working Set, т.е. несколько мегабайт или около того.
А надо искать во всем адресном пространстве процесса.

NtQuerySystemInformation с кодом SystemBasicInformation (0), получите
структуру SYSTEM_BASIC_INFORMATION, из нее берете поля
MinimumUserModeAddress и MaximumUserModeAddress, это и есть нижний и
верхний диапазоны адресов поиска. А вовсе не EntryPoint + Working Set,
что вообще само по себе бессмысленно.

C++
1
start += mbi.RegionSize; //переходим на следующий регион
И это тоже неправильно. Двигаться надо по страницам (4К), а не по регионам.

Еще желательно учесть, что искомая строка может лежать на границе двух страниц.

C++
1
while(start < ((DWORD)dwStart + dwMemSize))
Лучше сразу заменить (здесь и в других местах, где адреса) DWORD на DWORD_PTR.
Потому что на x64 указатели вытягиваются с 4 байт до 8 (в DWORD не влезет, а
ошибок компиляции не будет).

C++
1
2
3
4
5
6
7
8
9
10
if(     (mbi.State == MEM_COMMIT)            //если регион в состоянии передачи памяти
                &&                                    //и
                (mbi.Protect != PAGE_READONLY)        //регион не только для чнения
                &&                                    //и
                (mbi.Protect != PAGE_EXECUTE_READ)    //регион не тролько с исполнением программного кода и чтением
                &&                                    //и
                (mbi.Protect != PAGE_GUARD)            //регион без сигнала доступа к странице
                &&                                    //и
                (mbi.Protect != PAGE_NOACCESS)        //регион не защищён доступом к нему
                )//то
Это, как мне кажется, ненужное ограничение.
Все, что нужно проверять - это то, что страница закоммичена и
доступна на чтение.
1
2 / 2 / 0
Регистрация: 31.10.2013
Сообщений: 17
26.04.2015, 09:06  [ТС]
Убежденный, большое спасибо за комментарий. Совсем согласен, но есть вопросы:

1. Диапазон адресов я получаю теперь следующим образов (исходя из ваших слов):
C++
1
2
3
4
5
6
7
8
SYSTEM_INFO msi;
GetSystemInfo(&msi); //тут я получаю состояние системы.
 
//получаем минимальный адрес поиска
DWORD_PTR dwStart = (DWORD)msi.lpMinimumApplicationAddress;
 
//получаем максимальный адрес поиска
DWORD_PTR dwMemSize = (DWORD)msi.lpMaximumApplicationAddress;
Но это слишком много. Там же адреса не только нашего процесса.

2. Тупо не понимаю как постранично двигаться.
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
26.04.2015, 09:17
Лучший ответ Сообщение было отмечено Кирилл Романов как решение

Решение

Цитата Сообщение от Кирилл Романов Посмотреть сообщение
Но это слишком много.
Много - это когда вы то же самое на x64 будете делать.
А для 32-битных процессов диапазон поиска обычно получается около 2 Гб.

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

2. Тупо не понимаю как постранично двигаться.
Addr += PageSize (где PageSize = 4096).
1
2 / 2 / 0
Регистрация: 31.10.2013
Сообщений: 17
26.04.2015, 09:50  [ТС]
Цитата Сообщение от Убежденный Посмотреть сообщение
В этих полях минимальный и максимальный адреса, доступные для
использования в режиме пользователя.
Тогда я не знаю как получить диапозон адресов.
Ладно, вы мне очень помогли, спасибо.
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
26.04.2015, 10:08
Цитата Сообщение от Кирилл Романов Посмотреть сообщение
Тогда я не знаю как получить диапозон адресов.
lpMinimumApplicationAddress и lpMaximumApplicationAddress.
1
2 / 2 / 0
Регистрация: 31.10.2013
Сообщений: 17
26.04.2015, 10:24  [ТС]
Убежденный, и последний вопрос.

Мне отказаться стоит от регионов вообще?

C++ (Qt)
1
VirtualQueryEx(mem->m_hProc, (void *)start, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
эта функция не нужна получается? или же внутри региона уже читать по 4096 байт?

2. В чем приемущество просмотра памяти по страницам?
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
26.04.2015, 14:51
Лучший ответ Сообщение было отмечено Кирилл Романов как решение

Решение

Атрибуты защиты памяти могут устанавливаться для отдельных страниц,
поэтому двигаться лучше по страницам, а не по регионам.

Добавлено через 34 секунды
Цитата Сообщение от Кирилл Романов Посмотреть сообщение
эта функция не нужна получается?
Нужна. Без нее вы не узнаете атрибуты защиты страницы.
2
2 / 2 / 0
Регистрация: 31.10.2013
Сообщений: 17
27.04.2015, 01:06  [ТС]
Убежденный, спасибо Вам большое. У меня все получилось. А самое главное, что я все понял!
0
 Аватар для DaVillka
-1 / 8 / 6
Регистрация: 31.10.2015
Сообщений: 151
29.01.2016, 13:58
Убежденный, воспользовался кодом из этой теми для поиска своего текста в процессе. Немножко переделал,в соответствии с комментариями, но что то оно ищет слишком долго, и дико жрет оперативку. Не могли бы Вы подсказать, что я сделал не так?
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include <windows.h>
#include <iostream>
#include <psapi.h>//информация о памяти процесса
#include <fstream>//для вывода в документ адресов и значений по ним
using namespace std;
#pragma comment(lib, "psapi.lib")
 
//имя программы
#define PROGRAMM_NAME "L2PacketHack v3.5.34.176 by CoderX.ru Team"
 
 
//получить базовый адрес процесса
LPVOID GetBaseAddress(HANDLE hProc)
{
    //структура с информацией о процессе
    MODULEINFO miInfo;
 
    //получаем базовый адрес процесса
    if (GetModuleInformation(hProc, NULL, &miInfo, sizeof(miInfo)))
        return miInfo.EntryPoint;
    else
        return NULL;
}
 
//получить размер используемой памяти приложения(в байтах)
DWORD GetMemorySize(HANDLE hProc)
{
    //структура с информацией о процессе
    PROCESS_MEMORY_COUNTERS pmcInfo;
 
    //получаем информацию о процессе
    if (GetProcessMemoryInfo(hProc, &pmcInfo, sizeof(pmcInfo)))
        return (DWORD)pmcInfo.WorkingSetSize;
    else
        return 0;
}
 
 
void main()
{
    setlocale(LC_ALL, "Russian");//устанавливаем русский язык для вывода
 
    //ищем окно
    HWND hWnd = FindWindow(NULL, TEXT(PROGRAMM_NAME));
    if (!hWnd)
    {
        cout << "Программа не запущена.";
        return;
    }
 
    //получаем ID процесса
    DWORD dwPID;
    GetWindowThreadProcessId(hWnd, &dwPID);
    if (!dwPID)
    {
        cout << "Невозможно получить ID процесса.";
        return;
    }
 
    //получаем хэндл процесса
    HANDLE hProc;
    hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwPID);
    if (!hProc)
    {
        cout << "Невозможно получить хэндл процесса.";
        return;
    }
 
    SYSTEM_INFO msi;
    GetSystemInfo(&msi); //тут я получаю состояние системы.
 
    //получаем начальный адрес процесса
    DWORD_PTR dwStart = (DWORD)msi.lpMinimumApplicationAddress;
 
    //получаем размер занимаемой памяти
    DWORD_PTR dwMemSize = (DWORD)msi.lpMaximumApplicationAddress;
    DWORD_PTR PageSize = 4096;
    if (!dwMemSize)
    {
        cout << "Невозможно получить размер памяти, занимаемой приложением.";
        return;
    }
 
 
    cout << "Программа: "                    << PROGRAMM_NAME        << "\n"        <<
            "Handle Window: "                << hWnd                    << "\n"        <<
            "ProcessId: "                    << dwPID                << "\n"        <<
            "Handle Process: "                << hProc                << "\n"        <<
            "Начальный адрес: "                << dwStart                << "\n"        <<
            "Размер занимаемой памяти: "    << (dwMemSize / 1024)    << " кБ\n"    <<
            "\n\n\n\n";
 
    const WCHAR * signature = L"l2ph.exe";      // Последовательность которую будем искать
    size_t len_signature = lstrlenW(signature) * sizeof(WCHAR); // Длина последовательности.
 
    DWORD start = (DWORD)dwStart;//счётчик для цикла
    SIZE_T lpRead = 0;
 
    while(start < ((DWORD)dwStart + dwMemSize))
     {
        MEMORY_BASIC_INFORMATION mbi;
        
 
        int sz = VirtualQueryEx(hProc, (void *)start, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
 
        if(     (mbi.State == MEM_COMMIT)&&(mbi.Protect != PAGE_READONLY))
        {
            if(mbi.RegionSize != lpRead)
            {
                BYTE* lpData = (BYTE*)malloc(mbi.RegionSize);//резервируем место для массива lpData, размером в регион
                
                if(ReadProcessMemory(hProc, (LPCVOID)start, lpData, mbi.RegionSize, &lpRead))
                {
                   cout << "Поиск в регионе размером " << mbi.RegionSize << " байт\n";//поиск строки в массиве
                
                      BYTE *p = lpData;
                      while((p = (BYTE*)memchr(p, signature[0], mbi.RegionSize - len_signature + 1 - (p - lpData))) != 0)
                      {
                         if ( 0 == memcmp(p+1, signature + 1, len_signature - 1))
                         {
                            // найдено!!! в (p) адрес нашего буфера, где обнаружена последовательность.
                            // соответственно адрес в приложении равен: Start + (p - lpData);
                             printf("%d\n",lpData);
                         }
                         ++p;
                      }
 
                }
            }
        }
        Sleep(50);
        start += PageSize ;//переходим на следующий регион
    }
 
    cout << "\nГотово.";
 
    //закрываем хэндл процесса
    CloseHandle(hProc);
    system("Pause");
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
29.01.2016, 13:58
Помогаю со студенческими работами здесь

Поиск строки в памяти запущенного процесса и её изменение
Не могу решить задачку нужно считать строку из памяти процесса запущенной программы. RVA строки $0036D0C8 нужен ведь RVA не VA ...

Виртуальная память процесса, функции WinAPI
Всем доброго времени суток! Нужно написать программу, которая выводит информацию о виртуальной памяти процесса (задача сформулирована...

Совместимость оперативной памяти - Оперативная память
Доброго времени суток! Имею возможность установить 2 планки оперативностой памяти ,проблема в том что есть старая: Samsung И новую...

После замены оперативной памяти компьютер перезагружается / Оперативная память
Здравствуйте, на моем компьютере всего 2 слота под память. Стоит сейчас всего 2гб, решил поставить 4+4=8гб, стал компьютер перезагружаться....

Оперативная память для RYZEN, тест памяти DDR4. Одноканальность/двухканальность
С моими железяками, тест &quot;резонансного дзена&quot; получиться не скоро. Приборахлился еще одной планкой памяти. Corsair...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Логарифм записывается как: (x-2)log(x^2+2) - означает логарифм (x^2+2) по основанию (x-2). Унарный минус обозначается как ! */ #include <iostream> #include <stack> #include <cctype>. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru