2
#include <iostream>
#include <cassert>
#include <vector>
#include <ctime>
#include <cstdlib>
#include <Windows.h>

using namespace std;

char randomLetter()
{
    srand(time(0));
    char rValue;

    while(1)
    if((rValue=(rand()/129)) > 31) 
        return rValue;
}


int main()
{       
    vector<char> meegaString;

    for(int i=0; i < 10000000000; i++)
    {   
        meegaString.push_back(randomLetter());

                if(!(i%10000000)) 
            cout<<"There are: " <<i+1<<" chars in the list"<<endl;

    }

    system("pause");
    return 0;
}

运行此程序之前的 RAM 使用量约为 2500/8000 MB。当涉及到 3200 时,会抛出以下异常:

资源 gormandizer.exe 中 0x773c15de 处的未处理异常:Microsoft C++ 异常:内存位置 0x0045f864 处的 std::bad_alloc..

1) 为什么这个程序没有填满整个可用内存,尽管它是在 64 位操作系统上运行的?

2) 为什么只有 26% 的处理器(英特尔酷睿 i5)在使用?

4

3 回答 3

4
  1. 如前所述,向量的元素是连续存储的。此外,根据您的实现中使用的内存分配算法std::vector,它可能会尝试提前预分配内存;分配比用于减少malloc/new调用次数更多的内存。因此,它可能会请求比 32 位操作系统支持更多的内存(这可以解释为什么 64 位进程可以工作,但 32 位进程不会,尽管有足够的内存可用的)。

  2. 您的进程在 4 个内核中的一个上运行,并且非常繁忙,因此它占用了大约 25% 的 CPU 时间。其他过程将弥补其余部分。

另请参阅:关于向量内存分配的智能

于 2012-06-14T13:14:05.100 回答
2

anthony-arnold 的回答并没有错,如果我们对他的措辞采取一些自由,但仍然缺少一些东西。

正如其他人所提到的,如果您的 Core i5 是四核(i5 都是四核吗?),那么 25% 的人可能表明其中一个内核(即您的进程所在的内核)可能几乎 100% 忙,并且其他的大多是闲置的。与 anthony-arnold 的回答相反,25% 并不表示其他进程占用了另外 75%,而是说其他 75% 的可用 CPU 时间只是浪费了(空闲)。同样,如果您的 CPU 是四核,没有多线程测试应用程序,您的测试应用程序将无法消耗超过整体的 25%。

如果您正在寻找内存空间耗尽、折扣内存分配碎片和其他开销,那么您找到了。正如其他人所建议的那样,您的应用程序似乎已构建为 32 位应用程序。即使在 64 位操作系统上运行,您的应用程序也永远无法处理超过 32 位地址空间可以容纳的限制,即 4Gb。即便如此,还有很多其他开销,包括为操作系统保留的虚拟地址空间、程序和共享库空间、堆栈空间、分配给其他事物的堆空间以及堆空间开销。所以你的 meegaString 向量永远不会接近完整的 4Gb,甚至可能不会接近 2Gb(如果构建为大地址空间感知应用程序,它可能会超过 2Gb)。

现在关于 anthony-arnold 提到的“前向分配”点:所有 STL 容器都承诺摊销操作时间。std::vector 类承诺,平均而言(即摊销),push_back() 操作将是恒定时间(即 O(1)),这意味着随着其内容变得越来越大,执行 push_back() 将不需要更长的时间来做(如果确实如此,那将是 O(n))。有时执行 push_back() 需要的时间远超过 O(1),因为有时 push_back() 会导致容器的数据超出其当前分配的空间,它需要执行重新分配并将其当前内容移动到新位置,并删除其旧内容。在操作系统的配合下,一个良好实现的自定义编写的 STL 实现甚至可以做得更好,通过使用虚拟内存和 MMU 进行技巧,这样它就不必实际移动内容,它只是告诉操作系统告诉 MMU 制作数据虚拟内存页面映射到新位置,但这完全是另一个问题,无论如何您都不必担心,因为它会在幕后发生。在任何情况下,是的,std::vector 类必须“预分配”一个比它进行新分配时所需的更大的内存块,因为这是它可以承诺 O(1) push_back() 时间的唯一方法。如果每次执行 push_back() 时都必须将内容移动到新分配的缓冲区,那么 push_back() 的时间复杂度将是 O(n),而不是 O(1),

于 2012-06-15T15:41:12.197 回答
0

矢量类模板实现了一个动态数组,它需要一块连续的内存。

关闭主题 - 为此目的, 可以使用列表容器,但堆栈似乎是最好的解决方案。但是,无论是使用列表还是堆栈,它仍然会因相同的错误而崩溃(现在接近 4600 MB)。看起来很相似,但现在不是选择了无效数据结构的错。这是因为 32 位应用程序的可用内存非常有限,所以为了完全填满它,在 x64 平台上编译这个程序。

#include <iostream>
#include <stack>
#include <ctime>
#include <cstdlib>


using namespace std;

char randomLetter()
{
    srand(time(0));
    char rValue;

    while(1)
    if((rValue=(rand()/129)) > 31) 
        return rValue;
}


int main()
{       
    stack<char> meegaString;

    for(int i=0; i < 10000000000; i++)
    {   
        meegaString.push(randomLetter());

                if(!(i%10000000)) 
            cout<<"There are: " <<i+1<<" chars in the list"<<endl;

    }




    system("pause");
    return 0;
}
于 2012-06-14T13:56:04.207 回答