c++ - C++ winapi VirtualQueryEx 函数给了我“000000”
问题描述
我正在尝试显示有关系统上每个进程的虚拟内存的信息:
#include <windows.h>
#include <conio.h>
#include <tlhelp32.h>
#include <iostream>
using namespace std;
void main() {
HANDLE CONST hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
PROCESSENTRY32 proc;
TCHAR Buffer[1024];
TCHAR Buffer2[1024];
DWORD temp;
HANDLE CONST hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (INVALID_HANDLE_VALUE == hSnap)
{
return;
}
proc.dwSize = sizeof(PROCESSENTRY32);
Process32First(hSnap, &proc);
do {
MEMORY_BASIC_INFORMATION mbi = {};
wsprintf(Buffer, L" %s %d \n ", proc.szExeFile, proc.th32ProcessID);
WriteConsole(hStdOut, Buffer, lstrlen(Buffer), &temp, NULL);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, proc.th32ProcessID);
VirtualQueryEx(hProcess, 0, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
printf("Alloc = %p, base = %p , size = %d, type = %d, state = %p\n", mbi.AllocationBase, mbi.BaseAddress, mbi.RegionSize, mbi.Type,mbi.State);
} while (Process32Next(hSnap, &proc));
CloseHandle(hSnap);
}
输出如下所示:
我得到基地址和分配等于 0000000 并键入 0 如何获得正常值?我的意思是大小和状态似乎还可以,但其余的是“0000000”我不知道有什么问题
解决方案
您当前仅检索有关每个进程的第一个内存块的信息。一个进程通常会有很多内存块,而不仅仅是一个(数千到数万是非常典型的)。
下面是一些代码,用于检索和打印指定进程中每个数据块的状态。
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <iostream>
#include <string>
unsigned long show_module(MEMORY_BASIC_INFORMATION info) {
unsigned long usage = 0;
std::cout << info.BaseAddress << "(" << info.RegionSize / 1024 << ")\t";
switch (info.State) {
case MEM_COMMIT:
std::cout << "Committed";
break;
case MEM_RESERVE:
std::cout << "Reserved";
break;
case MEM_FREE:
std::cout << "Free";
break;
}
std::cout << "\t";
switch (info.Type) {
case MEM_IMAGE:
std::cout << "Code Module";
break;
case MEM_MAPPED:
std::cout << "Mapped ";
break;
case MEM_PRIVATE:
std::cout << "Private ";
}
std::cout << "\t";
int guard = 0, nocache = 0;
if ( info.AllocationProtect & PAGE_NOCACHE)
nocache = 1;
if ( info.AllocationProtect & PAGE_GUARD )
guard = 1;
info.AllocationProtect &= ~(PAGE_GUARD | PAGE_NOCACHE);
if ((info.State == MEM_COMMIT) && (info.AllocationProtect == PAGE_READWRITE || info.AllocationProtect == PAGE_READONLY))
usage += info.RegionSize;
switch (info.AllocationProtect) {
case PAGE_READONLY:
std::cout << "Read Only";
break;
case PAGE_READWRITE:
std::cout << "Read/Write";
break;
case PAGE_WRITECOPY:
std::cout << "Copy on Write";
break;
case PAGE_EXECUTE:
std::cout << "Execute only";
break;
case PAGE_EXECUTE_READ:
std::cout << "Execute/Read";
break;
case PAGE_EXECUTE_READWRITE:
std::cout << "Execute/Read/Write";
break;
case PAGE_EXECUTE_WRITECOPY:
std::cout << "COW Executable";
break;
}
if (guard)
std::cout << "\tguard page";
if (nocache)
std::cout << "\tnon-cacheable";
std::cout << "\n";
return usage;
}
unsigned long show_modules(HANDLE process) {
unsigned long usage = 0;
unsigned char* p = NULL;
MEMORY_BASIC_INFORMATION info;
for ( p = NULL;
VirtualQueryEx(process, p, &info, sizeof(info)) == sizeof(info);
p += info.RegionSize )
{
usage += show_module(info);
}
return usage;
}
int main(int argc, char **argv) {
int pid;
if (argc != 2) {
std::cerr << "Usage: " << argv[0] << " <process ID>\n";
return EXIT_FAILURE;
}
pid = std::stoi(argv[1]);
HANDLE process = OpenProcess(
PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
false,
pid);
unsigned long mem_used = show_modules(process);
std::cout << "Total memory used: " << mem_used / 10224 << "KB\n";
}
为了了解结果,以下是我系统上一个进程的前几行输出:
0000000000000000(64) Free
0000000000010000(64) Committed Mapped Read/Write
0000000000020000(4) Committed Mapped Read Only
0000000000021000(60) Free
0000000000030000(4) Committed Private
0000000000031000(60) Reserved Private
但请注意:您可能会获得比大多数典型流程更多的输出。该特定过程(Thunderbird)总共产生了 3,686 行输出。使用 Chrome 进行快速测试(使用几千兆字节的内存)会产生超过 46,000 行的输出(即系统为它跟踪超过 46,000 个单独的内存块)。
如果您要为系统中的每个进程打印一些内容,您可能需要对数据进行相当多的总结(但不知道为什么要这样,很难猜测您可能会得到什么样的结果想)。
推荐阅读
- javascript - 如果我们改变 setTimeout 和 setInterval 的顺序,为什么会额外执行 setInterval 的函数?
- r - 如何使用 R Shiny 中的传单地图修复“在没有活动反应上下文的情况下不允许操作”错误?
- python - pip 安装:我正在尝试在我的 MacBook Air 中安装 pip,但它显示语法错误:无效语法
- macros - 可以使用宏与任意数量的 car 和 cdr 调用(例如 cadaddr)进行 c[...]r 组合吗?
- oracle - Oracle Invalid number ORA-01722: invalid number 01722. 00000 - "invalid number"
- mysql - Navicat 过滤器功能比查询更快?如何?
- c# - C# TimeSpan ParseExact 奇怪的格式
- python - 如何将映射数据转换为字典,其中每个 XY 坐标都包含一个光谱?
- javascript - 如何在鼠标单击时更改时钟指针的度数?
- c++ - 我应该如何在 boost::asio 的客户端应用程序中同时使用 async_read_until 和 async_write?