【问题标题】:VirtualQueryEx error - too many pagesVirtualQueryEx 错误 - 页面过多
【发布时间】:2013-01-05 11:04:02
【问题描述】:

我正在使用 VirtualQueryEx 通过以下代码枚举模块的内存页:

unsigned char *p = (unsigned char *)module;
    MEMORY_BASIC_INFORMATION info;
    unsigned long usage = 0;
    for ( ;VirtualQueryEx(hProcess, p, &info, sizeof(info)) == sizeof(info);
        p += info.RegionSize ) 
    {
        printf("%#10.10x (%6uK)\t", info.BaseAddress, info.RegionSize/1024);

        switch (info.State) {
        case MEM_COMMIT:
            printf("Committed");
            break;
        case MEM_RESERVE:
            printf("Reserved");
            break;
        case MEM_FREE:
            printf("Free");
            break;
        }
        printf("\t");
        switch (info.Type) {
        case MEM_IMAGE:
            printf("Code Module");
            break;
        case MEM_MAPPED:
            printf("Mapped     ");
            break;
        case MEM_PRIVATE:
            printf("Private    ");
        }
        printf("\t");

        if ((info.State == MEM_COMMIT) && (info.Type == MEM_PRIVATE))
            usage +=info.RegionSize;

        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);

        switch (info.AllocationProtect) {
        case PAGE_READONLY:
            printf("Read Only");
            break;
        case PAGE_READWRITE:
            printf("Read/Write");
            break;
        case PAGE_WRITECOPY:
            printf("Copy on Write");
            break;
        case PAGE_EXECUTE:
            printf("Execute only");
            break;
        case PAGE_EXECUTE_READ:
            printf("Execute/Read");
            break;
        case PAGE_EXECUTE_READWRITE:
            printf("Execute/Read/Write");
            break;
        case PAGE_EXECUTE_WRITECOPY:
            printf("COW Executable");
            break;
        }

        if (guard)
            printf("\tguard page");
        if (nocache)
            printf("\tnon-cachable");
        printf("\n");
    }

代码取自这里的另一篇文章。

问题是:VirtualQueryEx 不会停止枚举当前模块的页面(它只是在内存超出进程时停止)并且结果是错误

这是我的输出和 VMMap 的输出

正如您从突出显示的地址开始看到的那样,页面都是错误的,VirtualQueryEx 甚至不会停止枚举它们。

我哪里错了?

【问题讨论】:

  • 您不能在正在运行的进程上安全地使用 VirtualQueryEx(),它可能会在您迭代它时分配或释放页面。这会产生这种不幸。它是一个调试器功能,调试器首先冻结一个进程中的所有线程。

标签: c++ windows winapi memory-management paging


【解决方案1】:

VMMap 知道 文件格式(.data、.text、ext 部分),VirtualQueryEx 不知道。 MEMORY_BASIC_INFORMATION.RegionSize - 所有页面具有相同保护属性的区域大小(屏幕截图中的 RW)。这就是计算区域 VMMap 和 VirtualQueryEx 不匹配的原因。

VirtualQueryEx 甚至不会停止枚举它们。

p += info.RegionSize

扫描整个用户模式虚拟内存地址空间。如果要停止扫描,请检查 AllocationBase 字段。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-16
    • 1970-01-01
    • 1970-01-01
    • 2019-09-21
    相关资源
    最近更新 更多