向量、指针、兔子和内存回收

Vectors, Pointers, Rabbits and reclaiming memory revisited

本文关键字:内存 指针 向量      更新时间:2023-10-16

简介

在之前的一篇文章中,我询问了关于悬空指针的问题。我明白我被建议使用Boost,一旦我完全掌握了经典指针和内存管理的基础知识,我就会重写我的程序,例如嵌入式设备携带一组有限的lib, Boost可能不可用,所以我希望能够做到这一点。

完整的解释

到目前为止,我的程序创建了许多指向vector对象的指针。在函数pop_rabbits( Vector<Rabbit*>, int amount)中,我将尝试从内存中删除一些指针,并从向量中弹出指针,如下所示:
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();
    }
}

但是兔子被弹出并删除,但是当我查看进程内存使用情况时,它并没有减少。

Valgrind输出:

==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)

这是系统相关的行为还是我忘记了一些东西来强制重新映射分配给进程的内存?

源代码
/*
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::FEMALE) ;
    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);
    }
}

这是系统相关的行为还是我忘记了一些东西来强制重新映射分配给进程的内存?

你所做的是对的。valgrind的报道是对的。由操作系统决定何时可以将内存分配给另一个进程。在删除指向内存的指针后,您并不总是会注意到内存使用计数的减少。

valgrind报告看起来很干净(可访问的通常来自标准库,例如std::cout;

您当然可以找到(运行--leak-check=full -v),但要准备好涉水过假阳性和/not-your-code/引用的页面