Memory testing program - tell me what you think!

Started by
8 comments, last by Spoonbender 19 years, 5 months ago
I have recently got a new stick of RAM and have been experiencing some problems (though I came to a conclusion that it has to do with Win98 being unable to use more than 512MB of ram). This sort of inspired me to make a rather simple program that tests the memory... The idea is VERY simple: the program keeps allocating dynamic variables until X mb of ram have been allocated. If an allocation fails, it informs the user. I have just one question I'd like to ask though - when watching a RAM-monitoring program while testing my application, I noticed it always allocates more than it's suppose to do - for instance, when I want it to test 100 MB it uses around 130 MB of memory... can someone explain to me why? I am pretty sure I have calculated the dLoops value correctly...

#include <iostream>
#include <iomanip>
#include <conio.h>
#include <windows.h>


class cChain    //just a random chain class that is 24 bytes big
{
 public:
 cChain(): prev(0), next(0) {}; //reset pointers
 cChain * prev;                 //pointer to previous element
 cChain * next;                 //pointer to next element
 int a;  //an integer just to fill the space
 int b;  //an integer just to fill the space
 int c;  //an integer just to fill the space
 int d;  //an integer just to fill the space
};

void SetColor(int dwFront, int dwBack); //this sets color of the text (for Failed)

using namespace std;

int main(int argc, char *argv[])
{
  unsigned int iRamAmount = 0;  //defines how much ram (mb) will be tested
  double dLoops = 0;            //how many loops have to be done
  cChain Chain;                 //our Chain of dynamically allocated variables
  cChain * Current = &Chain;    //pointer to a current element of the chain
  int iFailCount = 0;           //how many times did the test fail?
  double x;                     //counter used when allocating memory      
  double y;                     //counter used when freeing memory  
  int iCurPercent = 0;          //determines which percent we currently are
  bool bFail = 0;               //did something fail?
 
  
  cout << "Enter amount of RAM to be tested (MB): "; //asks the user
  cin >> iRamAmount;                                 //gets the user's answer
  cout << endl;
  
  if(iRamAmount <= 0) //if somebody put a value smaller/equal to zero...
    {
     cout << "ERROR: The value must be greater than zero!" << endl; //call him and idiot
     system("PAUSE");	 //wait
     return 0;     //and quit
    }
    
    
  dLoops = (double)iRamAmount*1024*1024 / sizeof(cChain);  //calculates how many times the loop has to be done
  
  while (kbhit()) getch();   // Empties buffer      
  
  cout << "Size of allocated block: " << sizeof(cChain) << " bytes." << endl;
  cout << "Memory will be allcoated " << setiosflags(ios::fixed) << setprecision(0) << dLoops << " times." << endl;
 
  cout << "Press any key to begin" << endl << endl;
  
  getch();
  
  for(x = 0; x < dLoops; x++)
    {
     Current->next = new cChain;  //dynamically allocate more memory!
     if(Current->next != 0)       //if it did not fail
          {
           Current->next->prev = Current;    //set the previous pointer of the next chain element to current chain element
           Current = Current->next;          //set current pointer to the next chain element
          }
     else                         //if allocation failed...
          {                   
          iFailCount++;           //increment fail count
          bFail = 1;              //set bFailed
          }
          
     if(dLoops/100*iCurPercent <= x+1)      //if we got to the next percent...
          {
          cout << "\r" << setw(3) << (int)((x+1)/dLoops * 100) << "% ; Fail count: " << setw(5) << iFailCount;   
          //the above simply displays nicely formatted percentage and fail count
          if(bFail)          //if allocation failed
                    {          
                     SetColor(4,0);
                     cout << "\tFailed!"; //display a red warning
                     SetColor(7,0);   
                    }          
          iCurPercent++;                  //increase the next percent we're looking for
          }

     if(kbhit())                    //if someone pressed something
          {
          cout << endl <<"Aborted" << endl;     //say abort
          getch();                              //empty the buffer
          break;                                //break the loop
          }
    }
  
  cout << endl << endl << "Freeing memory..." << endl << endl; //inform the user

  iCurPercent = 0;  //reset current percent since we're starting again...
  bFail = 0;        //reset bFail since we're starting again...
  
  
  for(y = 0; y < x; y++)   //do this loop as many times as we have allocated memory
    {
     if(Current->prev != 0)          //if the previous pointer is not 0 (shouldn't be)
          {
           Current = Current->prev;  //set current pointer to the previous element of chain
           delete Current->next;     //delete next element of chain (we're moving back)
          }
     else                            //if the previous pointer is 0 
          {
          bFail = 1;                 //something went wrong...
          }
        
     if(x/100*iCurPercent <= (y+1))   //if we got to the next percent...       
          {
          cout << "\r" << setw(3) << (int)((y+1)/x * 100) << "% ; Fail count: " << setw(5) << iFailCount;   
          //the above simply displays nicely formatted percentage and fail count
          if(bFail)          //if the previous pointer was 0 (shouldn't be)
                    {
                     SetColor(4,0);
                     cout << "\tPrevious pointer is 0"; //inform the user
                     SetColor(7,0);   
                    }
                    
          iCurPercent++;     //increment current percent                 
          }     

     if(kbhit())                    //if someone pressed something
          {
          cout << endl <<"Aborted" << endl;     //say abort
          getch();                              //empty the buffer
          break;                                //break the loop
          }          
    }  
    
  cout << endl << endl << "Test finished.\nMemory Tested: " << x/1024/1024 * sizeof(cChain) << " MB.\nFail count: " << iFailCount << endl;
  //inform user
  system("PAUSE");	 //wait
  return 0; // go home!
}



void SetColor(int dwFront, int dwBack)
{
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 16 * dwBack + dwFront);
}

As a side note, how "good" do you think this program is? Certainely it's not the most professional way to test RAM, but if I run it every now and then, getting no errors - do you think it's safe to assume my stick is ok...?
Comrade, Listen! The Glorious Commonwealth's first Airship has been compromised! Who is the saboteur? Who can be saved? Uncover what the passengers are hiding and write the grisly conclusion of its final hours in an open-ended, player-driven adventure. Dziekujemy! -- Karaski: What Goes Up...
Advertisement
When you allocate a block of memory, the runtime will also allocate additional book keeping information, as well as possibly padding to meet alignment restrictions. This tends to run from 4 to 32 bytes total per allocation on 32 bit systems. This extra memory tends to go inline immediately before the allocated memory block for bookkeeping inforation and immediately afterwards for padding.

Also, the runtime may allocate additional bookkeeping information out of line. If it does so, it usually runs from 8 to 16 bytes in size per allocation, again for 32 bit systems.

On top of that, in debug builds, the runtime may put additional padding on either side of the allocated block to check for buffer overruns.

Also, the runtime generally allocates in chunks from the operating system, when you reach the limit of what it's allocated, it may get another large chunk from the OS, which needs some amount of overhead to manage, and so on.

That's just off the top of my head. On the whole, there are a lot of places that extra memory used can be coming from.
That is really cool. you should make one for video memory if it is possible.
http://www.memtest86.com/
Quote:Original post by SiCrane
When you allocate a block of memory, the runtime will also allocate additional book keeping information, as well as possibly padding to meet alignment restrictions. This tends to run from 4 to 32 bytes total per allocation on 32 bit systems. This extra memory tends to go inline immediately before the allocated memory block for bookkeeping inforation and immediately afterwards for padding.

Also, the runtime may allocate additional bookkeeping information out of line. If it does so, it usually runs from 8 to 16 bytes in size per allocation, again for 32 bit systems.

On top of that, in debug builds, the runtime may put additional padding on either side of the allocated block to check for buffer overruns.

Also, the runtime generally allocates in chunks from the operating system, when you reach the limit of what it's allocated, it may get another large chunk from the OS, which needs some amount of overhead to manage, and so on.

That's just off the top of my head. On the whole, there are a lot of places that extra memory used can be coming from.


So essentially... you can't predict how much memory will be exactly allocated...?
Hmm, maybe if, instead of allocating X amount of times, I would keep allocating until I have allocated Y amount of memory... uuh.. so how do you retrieve the different info about RAM state ;) ?

Quote: http://www.memtest86.com/


Yes, I know, but I wanted to do something myself just for the heck of it...

Anywas, do you think I should include more tests? For instance, I could set the integers in my cChain: a = 2; b = 3; c = 4; d = a*b*c; and then check if d == 24. Think that would be a good idea...?
Comrade, Listen! The Glorious Commonwealth's first Airship has been compromised! Who is the saboteur? Who can be saved? Uncover what the passengers are hiding and write the grisly conclusion of its final hours in an open-ended, player-driven adventure. Dziekujemy! -- Karaski: What Goes Up...
Try to allocate large amounts of memory at a time, so you will
avoid great memory waste because of padding:

e.g. you can change the cChain class

#define SIZE 1024 class cChain    { public: cChain(): prev(0), next(0) {}; //reset pointers cChain * prev;                 //pointer to previous element cChain * next;                 //pointer to next element int a[SIZE];  //continuous memory block to fill the space};


The above code will allocate the "a" as a continuous block of
memory, so you will not have many memory leaks because of padding.

You can also try to set "SIZE" to different values and test what happens.
Thanks for the tip Jimmy, certainely a good idea!
Comrade, Listen! The Glorious Commonwealth's first Airship has been compromised! Who is the saboteur? Who can be saved? Uncover what the passengers are hiding and write the grisly conclusion of its final hours in an open-ended, player-driven adventure. Dziekujemy! -- Karaski: What Goes Up...
This comment is for your own good...

Stop what you are doing! Your program is as good as useless.
Sorry but you don't seem to know the first thing about properly checking RAM so you're only wasting your time.

Your program really is extremely inferrior to proper RAM testing programs. If you really want to know if your RAM is faulty then you must use a proper RAM testing program like: MemTest-86

DOH, someone else beat me to it...
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms
Quote:Original post by iMalc
This comment is for your own good...


So why do you think I posted this here...? :)
Comrade, Listen! The Glorious Commonwealth's first Airship has been compromised! Who is the saboteur? Who can be saved? Uncover what the passengers are hiding and write the grisly conclusion of its final hours in an open-ended, player-driven adventure. Dziekujemy! -- Karaski: What Goes Up...
To test whether the ram is faulty, you need to do a lot more than check whether allocation fails.
It might allocate the memory, and even write data to it, but when you try to read it, it might return a garbled value.

Or it might store the correct data *until* an adjacent cell is written to, which corrupts it. Or only some bits might be corrupted.

Basically, use a "proper" program for it. It gets really messy ,and practically impossible to do reliable under Windows, due to the use of virtual memory and other abstractions.
You really have no guarantee that what you're writing will end up using the entire ram stick when running it under Windows.

If you really want to do this yourself, I'd suggest you google for other mem-testing apps, and read the documentation for those. Some of them are open source, and some have pretty detailed information available on how they tackle the problem. Because it's a lot more complicated than just checking whether an allocation fails. :)

This topic is closed to new replies.

Advertisement