Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.76/21: Рейтинг темы: голосов - 21, средняя оценка - 4.76
 Аватар для Liss29
225 / 39 / 4
Регистрация: 18.11.2012
Сообщений: 1,638

Работа в VirtualAlloc()

24.05.2022, 06:46. Показов 4516. Ответов 49
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте! Хотелось бы получить помощь в следующем вопросе. Читаю книгу по WinApi автор Рихтер, в одной из глав посвящённой виртуальной памяти, есть задание, но программка не работает так как предполагается автором.
Собственно сам код чтобы не ходить вокруг да около. В куске кода:
C++
1
2
PVOID pvDummy = VirtualAlloc(NULL, mst.dwTotalPhys, 
      MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
Возвращается нулевое значение, а должен бы вернуться адрес для дальнейшей обработки. Этот участок кода должен сымитировать высокую нагрузку на память, но, повторюсь, всё идёт не так гладко, как хотелось бы.
Поясните, что не так, возможно, нужно что-то поменять в коде книга, всё же, писалась давно, и вполне возможно произошли серьёзные изменения!


Кликните здесь для просмотра всего текста
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
/******************************************************************************
Module:  MemReset.cpp
Notices: Copyright (c) 2000 Jeffrey Richter
******************************************************************************/
 
 
#include "..\CmnHdr.h"     /* See Appendix A. */
#include <tchar.h>
#include<stdio.h>
 
 
///////////////////////////////////////////////////////////////////////////////
 
 
int WINAPI _tWinMain(HINSTANCE hinstExe, HINSTANCE, PTSTR pszCmdLine, int) {
 
   chWindows9xNotAllowed();
 
 
   TCHAR szAppName[]  = TEXT("MEM_RESET tester");
   TCHAR szTestData[] = TEXT("Some text data");
 
   // Commit a page of storage and modify its contents.
   PTSTR pszData = (PTSTR) VirtualAlloc(NULL, 1024, 
      MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
   if(pszData == NULL)
   {
       TCHAR szError[100];
       wsprintf(szError, L"%s\t %x", "Get last error:", GetLastError());
 
       MessageBox(NULL, L"Virtual alloc faile.", szError, MB_OK);
       return EXIT_FAILURE;
 
   }
   lstrcpy(pszData, szTestData);
 
   if (MessageBox(NULL, TEXT("Do you want to access this data later?"), 
      szAppName, MB_YESNO) == IDNO) {
 
      // We want this page of storage to remain in our process but the 
      // contents aren't important to us anymore. 
      // Tell the system that the data is not modified.
 
      // Note: Because MEM_RESET destroys data, VirtualAlloc rounds
      // the base address and size parameters to their safest range.
      // Here is an example: 
      //    VirtualAlloc(pvData, 5000, MEM_RESET, PAGE_READWRITE)
      // resets 0 pages on CPUs where the page size is greater than 4 KB 
      // and resets 1 page on CPUs with a 4 KB page. So that our call to 
      // VirtualAlloc to reset memory below always succeeds, VirtualQuery 
      // is called first to get the exact region size.
      MEMORY_BASIC_INFORMATION mbi;
      VirtualQuery(pszData, &mbi, sizeof(mbi));
      VirtualAlloc(pszData, mbi.RegionSize, MEM_RESET, PAGE_READWRITE);
   }
   
   // Commit as much storage as there is physical RAM.
   MEMORYSTATUS mst;
   GlobalMemoryStatus(&mst);
   PVOID pvDummy = VirtualAlloc(NULL, mst.dwTotalPhys, 
      MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
 
   if(pvDummy == NULL)
   {
       TCHAR szError[100] = {0};
       wsprintf(szError, L"%s  %x", "GetLastError():", GetLastError());
 
       MessageBox(NULL, L"Virtual alloc faile.", szError, MB_OK);
       return EXIT_FAILURE;
   }
   // Touch all the pages in the dummy region so that any
   // modified pages in RAM are written to the paging file.
   ZeroMemory(pvDummy, mst.dwTotalPhys);
 
   // Compare our data page with what we originally wrote there.
   if (lstrcmp(pszData, szTestData) == 0) {
 
      // The data in the page matches what we originally put there.
      // ZeroMemory forced our page to be written to the paging file.
      MessageBox(NULL, TEXT("Modified data page was saved."), 
         szAppName, MB_OK);
   } else {
 
      // The data in the page does NOT match what we originally put there
      // ZeroMemory didn't cause our page to be written to the paging file
      MessageBox(NULL, TEXT("Modified data page was NOT saved."), 
         szAppName, MB_OK);
   }
   return(0);
}
 
 
//////////////////////////////// End of File //////////////////////////////////
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
24.05.2022, 06:46
Ответы с готовыми решениями:

Работа с VirtualAlloc
ребята, здравствуйте, очень нужна ваша помощь:) мне необходимо в учебных целях зарезервировать участок памяти определенного размера и...

VirtualAlloc
Всем привет!!! у кого есть любая роботающая програма с функцией VirtualAlloc??? Мне очень нада!!!!!!

VirtualAlloc
Необходимо зарезервировать память в определенном фиксированном регионе виртуального адресного пространства. const int...

49
 Аватар для Liss29
225 / 39 / 4
Регистрация: 18.11.2012
Сообщений: 1,638
26.05.2022, 08:51  [ТС]
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от QueryMonkey Посмотреть сообщение
попробуйте теперь уже и мое предложение, выше.
Это вы про то предложение, где предлагается кусками выделять, да?

Цитата Сообщение от QueryMonkey Посмотреть сообщение
А про выделить "всю физическую" вы конечно замахнулись.
Ну, я ни на что не замахивался, код я привёл, а что подразумевал автор точно сказать не могу, но параметр mst.ullTotalPhys говорит о размер всей физ. памяти так что... Короче говоря не ясно зачем это, не ясно как это должно выглядеть... Печалька)
0
844 / 353 / 68
Регистрация: 20.11.2012
Сообщений: 852
26.05.2022, 10:53
Лучший ответ Сообщение было отмечено Liss29 как решение

Решение

Liss29, чем компилируете и на какой системе запускаете код? Я про разрядность и размер физической памяти.
Если у вас установлено, например, 16 гб ОЗУ, Win64 и при этом вы собираете 32-х битный код, то GlobalMemoryStatus вернёт 16 гб, но в 32-х разрядном процессе столько выделить просто не выйдет.
Вот запустил у себя пример - при 32-х битном - ошибка о недостаточной памяти. При 64-х - уже ошибка о недостаточном размере файла подкачки. Файл подкачки должен быть достаточен, чтобы выгрузить всю ОЗУ. (У меня ОЗУ 80 Гб, а файл подкачки 4 Гб)...
Миниатюры
Работа в VirtualAlloc()  
0
844 / 353 / 68
Регистрация: 20.11.2012
Сообщений: 852
26.05.2022, 11:28
На 32-х битном, если использовать версию без Ex - даёт 2Гб и ошибку выделения. На 64-х при Ex - ошибку недостаточности файла подкачки.

В общем - всё верно - дело в фрагментации виртуальной памяти. Потому и невозможно выделить кусок непрерывной.
Код работает для x64, для x32 - нет.

Очевидно, когда писалась книга в ходу не было таких объемов. Если мне память не изменяет - Рихтер в этой книге где-то пишет, что на его машине 512 Мб ОЗУ.
0
 Аватар для Liss29
225 / 39 / 4
Регистрация: 18.11.2012
Сообщений: 1,638
27.05.2022, 02:57  [ТС]
Цитата Сообщение от WhiteP Посмотреть сообщение
чем компилируете и на какой системе запускаете код? Я про разрядность и размер физической памяти.
Visual studio 2019 x64, 8ГБ. И на виртуальной машине visual studio х86, 2Гб. Но на хосте, где установлено 8 ГБ памяти ОЗУ, 4 Гб файл подкачки, и студия 2019 компилирую проект как Debug х86.

Попробовал собрать на хостовой машине проект x64, НО ошибка. И указатель pvDummy == NULL.

Цитата Сообщение от WhiteP Посмотреть сообщение
Очевидно, когда писалась книга в ходу не было таких объемов. Если мне память не изменяет - Рихтер в этой книге где-то пишет, что на его машине 512 Мб ОЗУ.
Таких объёмов не было, но он в книге пишет о х64-ой версии windows 2000 ещё упоминается alpha x64, значит, хоть таких объёмов ОЗУ не было, но для 64-ёх разрядной винды он работал, и памяти было достаточно, хотя я не помню чтобы он писал о 512 МБ ОЗУ, возможно, я что-то упустил.

0
Нарушающий
417 / 305 / 46
Регистрация: 13.04.2022
Сообщений: 1,759
27.05.2022, 03:03
Что-то вы затряли. 1 ГБ у вас он выделяет?
0
 Аватар для Liss29
225 / 39 / 4
Регистрация: 18.11.2012
Сообщений: 1,638
27.05.2022, 03:46  [ТС]
Цитата Сообщение от QueryMonkey Посмотреть сообщение
1 ГБ у вас он выделяет?
Что, где выделяет, вы о чём?
0
Нарушающий
417 / 305 / 46
Регистрация: 13.04.2022
Сообщений: 1,759
27.05.2022, 03:54
Если вы

Цитата Сообщение от Liss29 Посмотреть сообщение
PVOID pvDummy = VirtualAlloc(NULL, 1L<<30, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
то один гиг он вам дает?
0
 Аватар для Liss29
225 / 39 / 4
Регистрация: 18.11.2012
Сообщений: 1,638
27.05.2022, 04:26  [ТС]
Цитата Сообщение от QueryMonkey Посмотреть сообщение
то один гиг он вам дает?
Если так, то что-то выделяется, по крайней мере pvDummy не нуль.
0
Нарушающий
417 / 305 / 46
Регистрация: 13.04.2022
Сообщений: 1,759
27.05.2022, 05:37
В 32 битах больше 3гиг не получить. Попробуйте в 64 битной программе аллокировать 3,4,5 и т.д.

Нащупайте максимум, сразу почувствуете дух инженеринга.
0
COM‐пропагандист
 Аватар для Замабувараев
936 / 785 / 149
Регистрация: 18.12.2014
Сообщений: 2,256
Записей в блоге: 4
27.05.2022, 06:30
Liss29, Я всё же настаиваю на вашем ответе: что, по‐вашему, ОС должна сделать когда в системе нет непрерывного куска памяти такого размера, который вы запросили?
0
 Аватар для Liss29
225 / 39 / 4
Регистрация: 18.11.2012
Сообщений: 1,638
27.05.2022, 07:42  [ТС]
Цитата Сообщение от Замабувараев Посмотреть сообщение
что, по‐вашему, ОС должна сделать когда в системе нет непрерывного куска памяти такого размера, который вы запросили?
Сгонять в магаз и купить мне плашку памяти, а что, и microsoft ни о чём, а мне приятно и полезно) Ну, а если серьёзно, то, по хорошему, должна бы выкинуть сообщение о нехватке памяти.

Добавлено через 27 секунд
Цитата Сообщение от QueryMonkey Посмотреть сообщение
В 32 битах больше 3гиг не получить. Попробуйте в 64 битной программе аллокировать 3,4,5 и т.д.
Сейчас попробую!

Добавлено через 14 минут
Цитата Сообщение от QueryMonkey Посмотреть сообщение
Нащупайте максимум, сразу почувствуете дух инженеринга.
Дух инженеринга я не прочувствовал), а то что вы предложили проделал. У меня выходит так: после шести попыток было пять раз выделено 6 ГБ и один раз 3 ГБ.
0
Нарушающий
417 / 305 / 46
Регистрация: 13.04.2022
Сообщений: 1,759
27.05.2022, 07:52
Liss29, сравните измеренные 33ГБ с размером вашего pagefile .

Они возможно близки.
0
 Аватар для Liss29
225 / 39 / 4
Регистрация: 18.11.2012
Сообщений: 1,638
27.05.2022, 08:00  [ТС]
Цитата Сообщение от QueryMonkey Посмотреть сообщение
Они возможно близки.
Короче говоря, если без лишних халиваров, то тот размер, которые я запрашиваю mst.ullTotalPhys = 14757395258967641292, невозможно выделить, просто потому что запрашиваемый размер много больше 6 Гигов. Так?
0
Нарушающий
417 / 305 / 46
Регистрация: 13.04.2022
Сообщений: 1,759
27.05.2022, 08:17
14 757 395 258 967 641 292

Я вижу 14 миллионов терабайт. Многоватенько.

Это значение чудесным образом совпало с величиной, которой debug версия компилятора
заполняет неинициализированные переменные.

Другими словами, в структуре мусор, скорее всего предыдущий вызов не исполнился. Проверьте код ошибки
0
844 / 353 / 68
Регистрация: 20.11.2012
Сообщений: 852
27.05.2022, 08:40
Цитата Сообщение от Liss29 Посмотреть сообщение
Короче говоря, если без лишних халиваров, то тот размер, которые я запрашиваю mst.ullTotalPhys = 14757395258967641292, невозможно выделить, просто потому что запрашиваемый размер много больше 6 Гигов. Так?
Когда заменили MEMORYSTATUS на MEMORYSTATUSEX - в поле dwLenght структуры её размер внесли перед использованием?
0
Нарушающий
417 / 305 / 46
Регистрация: 13.04.2022
Сообщений: 1,759
27.05.2022, 08:49
Вызывающий заполняет поле размера структуры, чтобы дать Винде понять к чему он готов.
0
 Аватар для Liss29
225 / 39 / 4
Регистрация: 18.11.2012
Сообщений: 1,638
27.05.2022, 09:00  [ТС]
Цитата Сообщение от QueryMonkey Посмотреть сообщение
Проверьте код ошибки
О каком коде ошибки идёт речь?

Цитата Сообщение от WhiteP Посмотреть сообщение
Когда заменили MEMORYSTATUS на MEMORYSTATUSEX - в поле dwLenght структуры её размер внесли перед использованием?
Конечно!
0
844 / 353 / 68
Регистрация: 20.11.2012
Сообщений: 852
27.05.2022, 09:03
Тут никаких холиваров нет.
У Рихтера код под x32 написан, о чём можно судить по использованию структуры MEMORYSTATUS, у которой поля типа DWORD, т.е. более 4 Гб содержать не могут в принципе. Если флаг increaseuserva в настройках системы не установлен, то в MEMORYSTATUS вернётся не более 2 Гб (т.е. вернётся меньшее из доступного пользовательского адресного пространства и физ.размера ОЗУ), иначе не более 3 Гб.
Книга написана в 2000 году, когда типичный объем ОЗУ для ПК не превышал 256-512 Мб.
0
 Аватар для Liss29
225 / 39 / 4
Регистрация: 18.11.2012
Сообщений: 1,638
27.05.2022, 09:04  [ТС]
@err,hr ERROR_INVALID_PARAMETER : Параметр задан неверно. unsigned int


Если я правильно понял, то нужно вернуться к прежнему вызову функции т.е.
C++
1
2
3
GlobalMemoryStatusEx(&mst);
   PVOID pvDummy = VirtualAlloc(NULL, mst.ullTotalPhys, 
      MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
0
844 / 353 / 68
Регистрация: 20.11.2012
Сообщений: 852
27.05.2022, 10:09
Цитата Сообщение от Liss29 Посмотреть сообщение
О каком коде ошибки идёт речь?
После GlobalMemoryStatusEx GetLastError.
Значение 14 757 395 258 967 641 292 некорректно. Столько быть не должно. У меня на скрине видно, что возвращается физ.объем памяти, как меньшее из объема ОЗУ и размера пользовательского АП для x64.


Цитата Сообщение от QueryMonkey Посмотреть сообщение
Вызывающий заполняет поле размера структуры, чтобы дать Винде понять к чему он готов.
Поле заполняется, чтобы дать понять Винде ту ли версию структуры (которая может быть изменена) передают функции. Если переданный и тот размер, что должен быть в текущей версии, отличаются, то выставляется ошибка ERROR_INVALID_PARAMETER и происходит возврат из функции:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
BOOL
WINAPI
GlobalMemoryStatusEx(
    LPMEMORYSTATUSEX lpBuffer
    )
{
    DWORD NumberOfPhysicalPages;
    SYSTEM_PERFORMANCE_INFORMATION PerfInfo;
    VM_COUNTERS VmCounters;
    QUOTA_LIMITS QuotaLimits;
    DWORDLONG AvailPageFile;
    DWORDLONG PhysicalMemory;
    NTSTATUS Status;
    DWORD Success;
    DWORDLONG address64;
 
    if (lpBuffer->dwLength != sizeof(*lpBuffer)) {
        SetLastError( ERROR_INVALID_PARAMETER );
        return FALSE;
    }
...
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
27.05.2022, 10:09

VirtualAlloc
Народ,подскажите кто знает.Разбираюсь с фун VirtualAlloc();Работа с участком памяти расспределенным этой функцией в принципе похожа на...

VirtualAlloc и VirtualProtect?
VirtualAlloc и VirtualProtect что из себя представляют даные функцыи,как с ними работать и что они делают, добрые программисты...

VirtualAlloc + ReadFile
Пользуюсь masm32 и функциями WINAPI. Хочу подгрузить файл в память выделенную с помощью VirtualAlloc. Однако, программа вылетает на...

VirtualAlloc и размеры
Друзья возник вопрос, кто обладает информацией, пожалуйста, поделитесь, в MSDN по этому поводу ничего не нашел. Проблема такая. ...

VirtualAlloc + ReadFile
INVOKE CreateFile,OFFSET fname, GENERIC_READ, NULL, NULL, OPEN_EXISTING, NULL,NULL mov HWNDFILE, eax invoke...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Установка ChatGPT (Codex) на Windows без использования Microsoft Store
Fabien159 28.10.2026
Здравствуйте всем читающим! Опишу процесс установки ChatGPT (Codex) на Windows, если по каким-то причинам у вас не получается устанавить его через Microsoft Store. И так: 1. Скачиваем с. . .
Программное добавление префикса в нумерацию документов
Maks 27.10.2026
Реализация из решения ниже выполнена в самописной конфигурации на БСП (помощь начинающему коллеге). Задача: Программно добавить префикс в нумерацию документов. Решение: В модуле объекта. . .
После закрытия оутлука продолжает висеть процесс в диспетчере задач
Maks 27.10.2026
С недавнего времени в продакшене возникла проблема: при закрытии оутлука в диспетчере задач продолжал висеть процесс outlook. exe. Проблема возникла после установки MS Office 2021 LTSC на машинах, под. . .
Baragoz - DPS/HPS бот для WoW 3.3.5a, многоязычный
AmbA 26.10.2026
Хотите ещё ботов? У меня есть один! А я пока отдохну от него. https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=12062&stc=1&d=1793007952 Инструкция внутри. https:/ / youtu. be/ VpfFZSUDGnQ. . .
Особенности gif сгенерированных в Си
russiannick 21.10.2026
Рассмотрим генерацию gif файлов, которые в Си имеют свои особенности. Gif представляет собой графический формат популярный в интернете. Посмотрим на палитру. Gif файл сгенерированный в си отличается. . .
FPS контроллер с анимированными Y-Bot и 3D-звуком miniaudio (Box3D, Recast, BehaviorTree.CPP, ozz-animation, ImGui, OpenGL и SDL3)
8Observer8 18.10.2026
Содержание блога | English Version Полное мультиплатформенное руководство по стартовому проекту с FPS-контроллером игрока, анимированными роботами Y-Bot с 4-слойным блендингом, 3D-физикой Box3D,. . .
Локальный http сервер
Argus19 17.10.2026
Локальный http сервер На работе, на двух локальных компьютерах круглосуточно работают программы опроса приборов с записью в книги Excel,которые раз в сутки записываются на сервер компании. Т. к. . . .
Копировать Windows на новый диск на UEFI
damix 17.10.2026
https:/ / uriesk. wordpress. com/ 2016/ 11/ 01/ move-window-10-to-ssd-on-a-uefi-dualboot-system-with-basic-linux-tools/ TL DR Вставляем диск, а старый подключаем через переходник, грузимся с лайва. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru