7

我正在运行此代码:

#include <iostream>
#include <cstddef>


int main(int argc, char *argv[]){
    int a1=0, a2=0;
    int a3,a4;

    int b1=++a1;
    int b2=a2++;

    int*p1=&a1;
    int*p2=&++a1;

    size_t st;
    ptrdiff_t pt;

    int i=0;
    while(true){
        printf("i: %d",i++);
    }
    printf("\n\ni now is: %d\n",i);
    return 0;
}

为什么我观察到图像内存(fiolet)如此减少: 在此处输入图像描述 图例:

在此处输入图像描述 我做了这个通用的 Win32 项目,而不是 CLR。我更改了代码,所以我会看到 int 何时最终变为负数。现在 while() 是:

    int i=0;
    while(0<++i){
        printf("i: %d",i++);
    }
    printf("\n\ni now is: %d\n",i);

很奇怪:请看看仅仅 30000 次迭代后发生了什么。为什么我们会在图像内存中看到这些波动?我现在可以看到这可能与 VMMap 本身有关,因为它仅在我选择“启动并跟踪新进程”时才会发生,而不是在“查看正在运行的进程”并指向运行从 VS2010 触发的 exe 时发生。这是“启动和跟踪”进程的屏幕: 在此处输入图像描述

我还观察到大量的内存分页,这大致开始于图像的这种下降(这个分页几乎加速并迅速触发了 RAM 限制,我已将其设置为 2GB): 在此处输入图像描述 这是一个仅“查看”的正在运行的进程(从 VS2010 运行) : 在此处输入图像描述

所以也许这里发生了一些受.NET应用程序内存管理的问题?我仍在等待我的 int 跨越两个补码的边界。

好吧...我必须再次编辑:事实证明,正如之前所想的那样 - 当仅查看(未启动)进程时也会出现内存图像减少的效果。下面附上 10 分钟后相同过程的图片(仍在等待将 int 变为负数): 在此处输入图像描述

这是:

在此处输入图像描述

所以我机器上最大的正2补码是2 147 483 647,最小的负是-2 147 483 648,这样很容易验证:

#include <limits>
const int min_int = std::numeric_limits<int>::min();
const int max_int = std::numeric_limits<int>::max();

它给了我相同的结果:-2 147 483 648 和 2 147 483 647

回到开头,当我评论除了 while() 循环之外的所有内容时——同样的事情发生了:在进程运行大约 10 分钟后图像正在减少,所以不是无用的代码导致了这种情况。但是什么?

4

1 回答 1

3

工作集很大程度上受操作系统的控制。您的代码所做的只是它在决定是否扩大或修剪您的工作集时考虑的一个因素。其他因素包括您的应用程序是否在前台,它的活跃程度,堆算法的贪婪程度,由于其他进程的需求而存在多少内存压力等。这是设计使然。

这些下降可能与 Windows 选择修剪您的工作集有关。由于最初加载的大部分代码可能只是用于初始化并且不参与循环,因此操作系统很容易根据 LRU 算法回收图像页面。

请注意,分配给图像大小的工作集并不是唯一被修剪的部分。

于 2012-06-12T00:02:10.993 回答