This is the mail archive of the libstdc++@sources.redhat.com mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

garbage collector never runs!!



I've been having some strange "memory leaks" in my code.  So i spent a
lot of time trying to track down the problem only to discover my "leak"
seems to caused by the default behaviour of the gc.
 
The garbage collector does not seem to be called on a regular basis for
small chunks of memory. When allocating large chunks of memory - garbage
collection works reasonably well.  When allocating small chunks of
memory - garbage collection only seems
to work if you delete every last scrap of memory.

Is this the correct behaviour for the gc??  Has anyone else seen this
problem?  I'm using Redhat 6.2 on a P3/600.  I'm using the egcs-20000612
image.

Following is the output from my test script.  I've also attached my
source test file and the simple script which generated this output.

As you can see, the gc runs when even when only 50% of the objects have
been deleted for large objects.

But for lots of small objects that take up the same amount of memory,
the gc only runs after deleting 100% of the objects.

Perhaps this isnt the best test case...  But this problem certainly
illustrates the issues i'm having in my code.

-Rob
 
> Allocating 200 chunks, each 500000 bytes long then freeing 100%
> Total allocated: 100773888
> Total freed:     100761600
> 
> Allocating 200 chunks, each 500000 bytes long then freeing 75%
> Total allocated: 100773888
> Total freed:     75571200
> 
> Allocating 200 chunks, each 500000 bytes long then freeing 50%
> Total allocated: 100773888
> Total freed:     50380800
> 
> Allocating 20000 chunks, each 5000 bytes long then freeing 100%
> Total allocated: 100315136
> Total freed:     100163584
> 
> Allocating 20000 chunks, each 5000 bytes long then freeing 75%
> Total allocated: 100315136
> Total freed:     0
> 
> Allocating 20000 chunks, each 5000 bytes long then freeing 50%
> Total allocated: 100315136
> Total freed:     0

#include <vector>
#include <iostream>
#include <unistd.h>
#include <ostream>
#include <sstream>
#include <fstream>

#include <string>
#include <memory>

using std::cout;
using std::endl;

//
// Takes snapshot of process status (info from ps cmd) at time of creation
//
class ProcessStatus
{
  public:

    ProcessStatus(); 
    unsigned long getVirtualMem() const { return _vmem; }

  private:

    unsigned long _vmem;
};


ProcessStatus::ProcessStatus() : _vmem(0)
{
    std::ostringstream stm;
    stm << "/proc/" << getpid() << "/stat" << std::ends;

    std::string fname = stm.str();
    std::ifstream ifs;
    ifs.open( fname.c_str() );
    if ( !ifs ) return;

    std::string dummy;

    for ( int i = 0; i < 22; ++i )
    {
      ifs >> dummy; 
    }

    ifs >> _vmem;  // virtual mem
}


//
//
//
void printDeltaT( const ProcessStatus & begin, const ProcessStatus & end )
{
  if ( begin.getVirtualMem() < end.getVirtualMem() )
  {
    cout << "Total allocated: "
         << end.getVirtualMem() - begin.getVirtualMem() << endl;
  }
  else
  {
    cout << "Total freed:     "
         << begin.getVirtualMem() - end.getVirtualMem() << endl;
  }
}


int main( int argc, char ** argv )
{
  int limit = 1000; 
  int memsz = 128;
  int perc  = 50;

  std::vector< void * > vdata;

  if ( argc >= 2 ) limit = atoi( argv[1] );
  if ( argc >= 3 ) memsz = atoi( argv[2] );
  if ( argc == 4 ) perc  = atoi( argv[3] );

  cout << endl;
  cout << "Allocating " << limit 
       << " chunks, each " << memsz << " bytes long"
       << " then freeing " << perc << "%" << endl;
  
  ProcessStatus stat1;

  for ( int i = 0; i < limit; ++i )
  { 
    vdata.push_back( malloc( memsz ) );
  }

  ProcessStatus stat2;

  for ( int i = 0; i < limit*perc/100; ++i )
  {
    free( vdata[i] );
  }

  ProcessStatus stat3;

  printDeltaT( stat1,stat2 );
  printDeltaT( stat2,stat3 );
}




# allocates 200 chunks of memory, each chunk is 500000 bytes
# deallocates 100%, 75%, and 50% respectively

./test 200 500000 100
./test 200 500000 75
./test 200 500000 50

# allocates 20000 chunks of memory, each chunk is 5000 bytes
# deallocates 100%, 75%, and 50% respectively

./test 20000 5000 100
./test 20000 5000 75
./test 20000 5000 50


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]