I am slightly concerned that this code may have a memory leak. I would like to know if in fact there is a leak, and also what is the correct way to go about this problem.
Description: I have a base class Pet with derived classes Cat, Dog, and Bird. I am parsing lines from a file, and depending on certain contents in that line, I need to create an instance of the derived classes, and then parse part of the line again in a specific way.
Here is a sample file:
Dog Spot Brown,Labrador,5
Cat Felix Black,7
Bird Polly Green,Parrot,12,Crackers
And some code:
class Pet
{
protected:
string _type;
string _name;
string _desc;
public:
Pet();
bool ParseLine(std::string line);
string Type() { return _type; }
string Name() { return _name; }
string Desc() { return _desc; }
};
class Dog : public Pet
{
private:
string _color;
string _type;
int _age;
public:
Dog(string type, string name, string desc);
bool ParseDesc(string desc);
};
Main Code:
ifstream infile(filename, ifstream::in);
string line;
while(getline(infile, line))
{
Pet* pet = new Pet(); // "new" called once
if(pet->ParseLine(line))
{
if(pet->Type() == "Dog")
{
pet = new Dog(pet->Type(), pet->Name(), pet->Desc()); // "new" called again
pet->ParseDesc(pet->Desc());
}
else if(pet->Type() == "Cat")
{
// ...
}
}
}
Basically what happens is this:
I take a line from the file and parse it into three fields (this is what ParseLine() does:
Type (Dog, Cat, Bird, etc.)
Name (Spot, Felix, Polly, etc.)
Description ("Brown,Labrador,5", "Black,7", "Green,Parrot,12,Crackers", etc)
I then assign these three fields to my Pet* variable.
Then, according to the value in Pet*->Type(), I parse Pet*->Desc() to get the additional information for that particular type of animal.
I am worried about calling operator “new” twice. I think there is probably a better way to format the code that could avoid this altogether.
I would really like to keep my getline() routine. I do NOT want to peek at the line to determine the type, and then decide how to create my instance.
Also, I have to reassign my variables _type, _name, and _desc, when I recreate the Dog(), and I’d rather not have to do that.
Thanks.
—
Specifically, how do I avoid this:
Pet* pet = new Pet();
pet->ParseLine(line);
string type = pet->Type();
string name = pet->Name();
string desc = pet->Desc();
delete pet;
if(type == "Dog")
{
Pet* dog = new Dog(type, name, desc);
dog->ParseDesc(desc);
}
Yes, this causes a memory leak, since you allocate a
new Pet()which is never deleted and the pointer to it is overridden with either anew Dog()or something else.I would suggest you create a so-called factory function, which reads a line from the file, and creates the type of
Petthe line states.