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 usage before running this program was approximately 2500/8000 MB. When it comes to 3200, the following exception is thrown:

Unhandled exception at 0x773c15de in Resources gormandizer.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x0045f864..

1) Why this program didn't fill the whole available memory , although it was working on a 64 bit OS?

2) Why only 26 percent of processor(intel core i5) were in usage?

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
0x6B6F77616C74
  • 2,559
  • 7
  • 38
  • 65
  • 4
    I _think_ it may be that `vector` requires a contiguous block of memory. So regardless of how much memory is available, a continguous block of memory of the required size must be available. – hmjd Jun 14 '12 at 12:55
  • Vector is not a linked list but a dynamic array? You have surprised me a lot :) – 0x6B6F77616C74 Jun 14 '12 at 12:58
  • 2
    from the C++ standard: _The elements of a vector are stored contiguously,.._ – hmjd Jun 14 '12 at 13:01
  • 1
    Your addresses look like those from a 32bit process. Even on a 64bit OS, a 32bit Can obviously never address more than 4gb. For your vector, you should reserve() it so it doesnt have to reallocate, so you dont run into the problem that it needs a new contiuous chunk. – PlasmaHH Jun 14 '12 at 14:04

3 Answers3

4
  1. As noted, the elements of a vector are stored contiguously. Also, depending on the memory allocation algorithm used in your implementation of std::vector, it is probably attempting to pre-allocate memory ahead of time; allocating more memory than is being used to cut down on the number of malloc/new calls. As such, it might be getting to the point where it's requesting more memory than a 32-bit OS can support (which would explain why a 64-bit process would work, but a 32-bit process wouldn't, despite having enough memory available).

  2. Your process is running on one core out of 4, and it's quite busy, hence it's taking up approximately 25% of the CPU time. Other processes would make up the rest.

See also: Being Smart About Vector Memory Allocation

Community
  • 1
  • 1
Anthony
  • 12,177
  • 9
  • 69
  • 105
  • 1
    +1 for forward allocation. @kutacz, It may be interesting to `reserve()` prior to the loop and check if it processes more chars. – hmjd Jun 14 '12 at 14:16
2

anthony-arnold's answer is not incorrect, if we take some liberty with his wording, but there's something still missing.

As others have mentioned, if your Core i5 is a quad-core (are all i5's quad core?), then 25% might suggest that perhaps one of the cores (i.e. the core your process was on) is nearly 100% busy, and the others are mostly idle. Contrary to anthony-arnold's answer, the 25% does not indicate that other processes are taking up the other 75%, it's saying that the other 75% of available CPU time is simply wasted (idle). Again, if your CPU is quad core, without a multithreaded test application, your test app isn't going to be able to consume more than 25% of the whole.

If you were looking for memory space exhaustion, discounting memory allocation fragmentation and other overhead, you found it. As others suggested, your app appears to have been built as a 32-bit app. Even running on a 64-bit OS, your app will never be able to address more than the limit of what a 32-bit address space can hold, which is 4Gb. Even then, there is a lot of other overhead, including virtual address space reserved for the OS, program and shared library space, stack space, and heap space allocated to other things as well as heap space overhead. So your meegaString vector will never even get close to a full 4Gb, probably not even close to 2Gb (perhaps it might get a little over 2Gb if built as a large-address-space-aware app).

Now in regard to the "forward allocation" point that anthony-arnold mentions: All STL containers make promises about amortized operation time. The std::vector class promises that, on average (i.e. amortized), a push_back() operation will be constant time (i.e. O(1)), which means that as its contents get larger & larger, doing a push_back() will not take longer & longer to do (if it did, it would be O(n)). Occasionally it will take much more than O(1) to do a push_back(), because occasionally push_back() will cause the container's data to exceed its currently-allocated space, and it will need to perform a reallocation and move its current contents to the new location, and delete its old contents. With cooperation from the OS, a well-implemented custom-written STL implementation can do even better than that by playing tricks with virtual memory and the MMU so that it doesn't have to actually move the contents, it just tells the OS to tell the MMU to make the data's virtual memory pages map to the new location, but that's another issue entirely and you don't need to worry about it anyway, because it would happen behind the scenes. In any case, yes, the std::vector class MUST "pre-allocate" a larger block of memory than required any time it makes a new allocation, because that's the only way it can promise O(1) push_back() time. If it had to move the contents to a newly-allocated buffer every time you did a push_back(), then push_back()'s time complexity would be O(n), not O(1), because the time to do a push_back() would get longer & longer the larger the vector's data is.

phonetagger
  • 7,701
  • 3
  • 31
  • 55
0

The vector class template implements a dynamic array, which requires a contiguous block of memory.

To close down the topic - for this purpose ,the list container can be used, but stack seems to be the best solution. However, either with list or stack, it still crashes with the same error (now nearby 4600 MB). Looks similar, but now it's not the fault of an invalid data structure selected. This occurs because 32-bit aplications has very circumscribed memory available, so in order to fully cram it, compile this program on the x64 platform.

#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;
}
0x6B6F77616C74
  • 2,559
  • 7
  • 38
  • 65
  • stack is just a container adaptor defaulting to using std::deque, so the "best solution" would be deque, and then you could also explain why (because deque allocates in chunks) – PlasmaHH Jun 14 '12 at 14:02