Search code examples
c++memory-leaksvalgrindcomposition

Memory leak reported by valgrind in composition


I have a code which looks ok, but when I run Valgrind it is showing leak for fields which is allocated with new in setNumberOfFields() function. Here are excerpts of my code:

class arcField {
public:
    arcField();
    ~arcField();
};

arcField::arcField(){}

arcField::~arcField() {}

class arcRecord {
public:
    char       *recordType;                    
    int         numberOfFields;                 
    arcField   *fields;     

    arcRecord(){}
    ~arcRecord();
    void setNumberOfFields(int num);
};

arcRecord::~arcRecord() {
    if(fields) {
        delete [] fields;
    }
    fields = 0;
}

void arcRecord::setNumberOfFields(int num) {
       if(fields) {
       delete [] fields;
    }
    fields = 0;
    fields = new arcField[num];   // line number 335
}

int main() {
    int index = 1;
    arcRecord records[1];
    for(int i = 0; i <= 1; i++) {
    records[i].setNumberOfFields(index);  
    return 0;
}

records[i].setNumberOfFields(tmp_int); // 940 line in valgrind.records is object of type arcRecord.

Valgrind Output:

==12647== 8 bytes in 1 blocks are definitely lost in loss record 33 of 642
==12647==    at 0x4A07152: operator new[](unsigned long) (vg_replace_malloc.c:363)
**==12647==    by 0x705BC8: arcRecord::setNumberOfFields(int) (recordFF.cc:335)**
==12647==    by 0x707B2F: arcRecordList::loadConfigFile(cvConfig&) (recordFF.cc:940)
==12647==    by 0x7078C7: arcRecordList::loadConfigFile(char const*) (recordFF.cc:894)
==12647==    by 0x70771D: arcRecordList::arcRecordList(char const*) (recordFF.cc:883)
==12647==    by 0x5EE131: cvComericaArchive::cvComericaArchive() (cvComericaArcFuncs.cc:62)
==12647==    by 0x45581F: ArchInterface::ArchInterface(std::string const&, char const*) (ArchInterface.cc:115)

I am not sure why it is showing leak at line 335 whereas the destructor is called for the arcField object. I am not sure about this error. I guess the destructor of arcRecord is not getting called which is not deleting the arcField object.


Solution

  • I am by far, not an expert in C++ / Valgrind, but I think you could have a memory leak if arcRecord::setNumberOfFields is called multiple times.

    In such cases the pointer to the arcField[] stored in fields would simply be replaced by the new one pointing to the memory allocated by the new arcField[num], without the existing array in memory being actually deleted.

    The destructor would only be able to delete the most recently allocated arcField[], (to which fields points) but not the ones allocated previously, to which you would have no pointer at all.

    You should maybe initialise all your pointers to 0:

    char       *recordType = 0;
    int         numberOfFields = 0;
    arcField   *fields = 0;   
    

    and then in arcRecord::setNumberOfFields check if fields is set already and if yes, delete it before allocating.

    void arcRecord::setNumberOfFields(int num) {
        if(fields) {
            delete [] fields;
        }
        fields = new arcField[num];
    }