开发者

Vectors, Pointers, Rabbits and reclaiming memory revisited

Brief Description

In a previous post I asked around about a problem with dangling pointers. I understood that I'm advised to use Boost and I will rewrite my program as soon I fully got the basics about classical pointers and memory management, as for example embedded devices carry a limited set of lib's and boost might not be available so I want to be able to do this the hard way.

Complete Explanation

By now my program creates a lot of pointers to Rabbit objects in a vector. In a function pop_rabbits( Vector<Rabbit*>, int amount) I'll attempt to delete a few from memory and pop the pointers from the vector like this :

void pop_rabbits(vector<Rabbit*> & rabbits, int n){
    vector<Rabbit*>::iterator rabbits_iterator ;

    for(int r = 0 ; r < n ; r++ ){
        Rabbit* dead_rabbit ;
        dead_rabbit = rabbits.back() ;
        delete dead_rabbit ;
        rabbits.pop_back();
    }
}

But rabbits get popped and deleted but in when I look at the process memory usage, it doesn't decrease.

Valgrind output :

==26286== 
==26286== HEAP SUMMARY:
==26286==     in use at exit: 117,290 bytes in 6,471 blocks
==26286==   total heap usage: 11,503 allocs, 5,032 frees, 222,872 bytes allocated
==26286== 
==26286== LEAK SUMMARY:
==26286==    definitely lost: 0 bytes in 0 blocks
==26286==    indirectly lost: 0 bytes in 0 blocks
==26286==      possibly lost: 0 bytes in 0 blocks
==26286==    still reachable: 117,290 bytes in 6,471 blocks
==26286==         suppressed: 0 bytes in 0 blocks
==26286== Rerun with --leak-check=full to see details of leaked memory
==26286== 
==26286== For counts of detected and suppressed errors, rerun with: -v
==26286== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 18 from 7)

Is this system related behavior or did I forget something to actually force remapping of the memory assigned to the process ?

Source Code

/*
This will become an exercise on dynamic memory ;
Im going to create a lot of breeding rabbits :)
the application will wait for the user to give his fiat for mating, LOL 
*/

using namespace std ;

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <iterator>
#include <sys/time.h>
#include <sys/resource.h>

class Rabbit {
    public:
        enum sexes { MALE = 0x1, FEMALE = 0x2 } ;
        int sex ;
        bool has_mated ;
        Rabbit();
        ~Rabbit();
        void setSexe(int sex);
        void match( vector<Rabbit*> &rabbits ); //returns true if it found a female and makes the female breed.
        void breed( Rabbit &partner, vector<Rabbit*> &rabbits ); //create ofspring from the female mixing in the genes from the male
};

Rabbit::Rabbit(){
    this->sex = random() % 2 + 1 ; //random m/f
    this->has_mated = false ;
}

Rabbit::~Rabbit(){
    cout << "Aaaaahggg...beybeye cruel world !\n";
}

void Rabbit::setSexe( int sex ){
    this->sex = sex ;
}

void Rabbit::match(vector<Rabbit*> &rabbits){
    int s = rabbits.size() ;
    int r = 0 ;
    for(r ; r < s ; r++ ){
        Rabbit* partner_ptr = rabbits.at(r) ;

        if( partner_ptr->sex == Rabbit::MALE ){
            this->breed(*partner_ptr, rabbits);
        }
    }
}

void Rabbit::breed( Rabbit &partner, vector<Rabbit*> &rabbits ){
    int offspring, sex ; 
    offspring = random() % 4 + 3 ;
    cout << "breeding " << offspring << " rabbits..."  << endl ;
    Rabbit* temp_rabbit ;
    for(int i=0; i < offspring; i++){
        int sex = random() % 2 + 1 ;
        temp_rabbit = new Rabbit() ;
        temp_rabbit->setSexe(sex);
        rabbits.push_back(temp_rabbit);
        cout << "one rabbit has been born." << endl ;
    }
    this->has_mated = true ;
}

//makes rabbits date each other
void match_rabbits(vector<Rabbit*> & rabbits){

    cout << "matching rabbits..." << endl ;

    for(int r = 0; r < rabbits.size() ; r++ ){

        Rabbit* nth_rabbit_p = rabbits.at(r);

        if( nth_rabbit_p->sex == Rabbit::FEMALE && nth_rabbit_p->has_mated == false){
            cout << "found a female" << endl ;
            nth_rabbit_p->match(rabbits) ;
            break ;
        }

    }
}

void pop_rabbits(vector<Rabbit*> & rabbits, int n){
    vector<Rabbit*>::iterator rabbits_iterator ;

    for(int r = 0 ; r < n ; r++ ){
        Rabbit* dead_rabbit ;
        dead_rabbit = rabbits.back() ;
        delete dead_rabbit ;
        rabbits.pop_back();
    }
}

int main( int argc , const char* argv[] ){


    srand(time(NULL));

    vector<Rabbit*> rabbits = vector<Rabbit*>(0) ;

    Rabbit* adam ;
    adam = new Rabbit();
    adam->setSexe(Rabbit::MALE) ;

    Rabbit* eve ;
    eve = new Rabbit() ;
    eve->setSexe(Rabbit::开发者_如何学PythonFEMALE) ;

    char * input;
    input = new char[2] ;

    try{

        //populate with 2 rabbits.

        rabbits.push_back(adam);
        rabbits.push_back(eve);

        do {


            //memory_usage = getrusage(RUSAGE_SELF, struct rusage *usage);
            if(rabbits.size() < 2){ 
                break ;
            }

            cout << rabbits.size() << " rabbits ( " << ( rabbits.size() * sizeof(Rabbit) )/1024 << "K )" << endl ;

            cout << "Shoot some rabbits ? (Y/N) :" << endl ;

            delete[] input ;
            input = new char[2] ;
            cin.getline(input,2);       

            if( strcmp(input,"Y") == 0 || strcmp(input,"y") == 0){
                cout << "How many ? :" << endl ;

                delete[] input ;
                input = new char[16] ;
                cin.getline(input,16);

                pop_rabbits(rabbits, atoi(input));

                continue ;
            } 

            cout << "Continue ? (Y/Q) :" << endl ;

            delete[] input ;
            input = new char[2] ;
            cin.getline(input,2);   

            if(strcmp(input,"Y") == 0 || strcmp(input,"y") == 0){
                match_rabbits(rabbits);//let the rabbits date
            }

            if(strcmp(input,"Q") == 0 || strcmp(input,"q") == 0){
                break ;
            }

        } while( true );

        exit(0);

    } catch ( exception& e ){
        cout << e.what() << endl ; //print error
        exit(1);
    }

}


Is this system related behavour or did i forgot somehing to actually force remapping of the memory assigned to the process ?

What you've done is right. What valgrind is reporting is right. It's up to the operating system to decide when that memory can be allocated to another process. You aren't always going to notice a decrease in the memory usage count after deleting pointers to memory you own.


FWIW that valgrind report looks clean (reachables frequently stem from the standard library, e.g. std::cout;

You can of course find out (run with --leak-check=full -v) but be prepared to wade through pages of false positives and /not-your-code/ references

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜