PSAPI.h 的 QueryWorkingSet 函数中使用的PSAPI_WORKING_SET_INFORMATION缓冲区的实际大小是多少



我想使用PSAPI中可用的函数QueryWorkingSet,但我在实际定义缓冲区pv的大小时遇到了问题。这是代码:

#include <Windows.h>
#include <Psapi.h>
#include <iostream>

void testQueryWorkingSet()
{
unsigned int counter;
HANDLE thisProcess = GetCurrentProcess();
SYSTEM_INFO si;
PSAPI_WORKING_SET_INFORMATION wsi, wsi2;
GetSystemInfo(&si);
QueryWorkingSet(thisProcess, &wsi, sizeof(wsi));
DWORD wsi2_buffer_size = (wsi.NumberOfEntries) * sizeof(PSAPI_WORKING_SET_BLOCK);
if (!QueryWorkingSet(thisProcess, &wsi2, wsi2_buffer_size))
{
std::cout << "ERROR CODE : " << GetLastError() << std::endl;
abort();
}
}
int main(int argc, char * argv[])
{
testQueryWorkingSet();
int* test = new int[1000000];
testQueryWorkingSet();
}

在第一次调用testQueryWorkingSet()时,我总是以调用abort()和错误代码24或998结束。分别解释为:wsi2_buffer_size太低,wsi2_buffer_size太大。

现在我不知道这个变量应该取什么值,我试着:

  • 计算包括NumberOfEntries字段在内的所有内容,即DWORD wsi2_buffer_size = sizeof(wsi.NumberOfEntries) + wsi.NumberOfEntries * sizeof(PSAPI_WORKING_SET_BLOCK);=>错误998
  • 只计算条目的数量,即上面给出的代码=>错误998
  • 变量wsi2的大小,即DWORD wsi2_buffer_size = sizeof(wsi2);=>错误24

我们应该使用这个函数的方式肯定有一些我不理解的地方,但我找不到什么。我试着调整那里给出的代码,即:

#include <Windows.h>
#include <Psapi.h>
#include <iostream>

void testQueryWorkingSet()
{
unsigned int counter;
HANDLE thisProcess = GetCurrentProcess();
SYSTEM_INFO si;
PSAPI_WORKING_SET_INFORMATION wsi_1, * wsi;
DWORD wsi_size;
GetSystemInfo(&si);
wsi_1.NumberOfEntries = 0;
QueryWorkingSet(thisProcess, (LPVOID)&wsi_1, sizeof(wsi));
#if !defined(_WIN64)
wsi_1.NumberOfEntries--;
#endif
wsi_size = sizeof(PSAPI_WORKING_SET_INFORMATION)
+ sizeof(PSAPI_WORKING_SET_BLOCK) * wsi_1.NumberOfEntries;
wsi = (PSAPI_WORKING_SET_INFORMATION*)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, wsi_size);
if (!QueryWorkingSet(thisProcess, (LPVOID)wsi, wsi_size)) {
printf("# Second QueryWorkingSet failed: %lun"
, GetLastError());
abort();
}
}
int main(int argc, char * argv[])
{
testQueryWorkingSet();
int* test = new int[1000000];
testQueryWorkingSet();
}

此代码仅适用于对testQueryWorkingSet()的1次调用,第二次调用中止,错误代码为24。以下是简单的问题:

  1. 如何在一个可以连续多次调用的函数中使用QueryWorkingSet
  2. 在给定PSAPI_WORKING_SET_INFORMATION的情况下,文档中参数cb的值是多少

这两个例子都完全忽略了QueryWorkingSet()第一次调用的返回值和错误代码。您只在第二次通话时进行错误处理。

您的第一个示例失败了,因为在为QueryWorkingSet()的第二次调用计算wsi2_buffer_size时,您没有考虑PSAPI_WORKING_SET_INFORMATION的整个大小。即使第一次调用成功,如果返回的NumberOfEntries为>1.

您的第二个示例是将错误的缓冲区大小值传递给QueryWorkingSet()的第一个调用的cb参数。您传递的只是单个指针的大小,而不是整个PSAPI_WORKING_SET_INFORMATION的大小。错误24是ERROR_BAD_LENGTH。您需要使用sizeof(wsi_1)而不是sizeof(wsi)

我建议在循环中调用QueryWorkingSet(),以防工作集在查询其大小的调用和获取其数据的调用之间发生实际变化。

此外,当你使用完内存后,一定要释放你分配的内存。

话虽如此,尝试更多的生活方式:

void testQueryWorkingSet()
{
HANDLE thisProcess = GetCurrentProcess();
PSAPI_WORKING_SET_INFORMATION *wsi, *wsi_new;
DWORD wsi_size;
ULONG_PTR count = 1; // or whatever initial size you want...
do
{
wsi_size = offsetof(PSAPI_WORKING_SET_INFORMATION, WorkingSetInfo[count]);
wsi = (PSAPI_WORKING_SET_INFORMATION*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, wsi_size);
if (!wsi)
{
printf("HeapAlloc failed: %lun", GetLastError());
abort();
}
if (QueryWorkingSet(thisProcess, wsi, wsi_size))
break;
if (GetLastError() != ERROR_BAD_LENGTH)
{
printf("QueryWorkingSet failed: %lun", GetLastError());
HeapFree(GetProcessHeap(), 0, wsi);
abort();
}
count = wsi->NumberOfEntries;
HeapFree(GetProcessHeap(), 0, wsi);
}
while (true);
// use wsi as needed...
HeapFree(GetProcessHeap(), 0, wsi);
}

相关内容

  • 没有找到相关文章

最新更新