Hi, I'm having an issue in my program when I try to call delete in my destructor.
Can someone take a look and see what I doing wrong? I've looked it over and over but I just can't figure out what's wrong.

destructor code:

StudentRecord::~StudentRecord(){		// Destructor
	delete[] m_firstName;
	delete[] m_lastName;
}

and this is my constructor code:

StudentRecord::StudentRecord(char* first,char* last,unsigned int id,float mark){	// Overloaded constructor
	m_firstName = strcpy(new char[strlen(first)+1],first);
	m_lastName = strcpy(new char[strlen(last)+1],last);
	m_id = id;
	m_mark = mark;
}

Here is the full code for my project in case it's needed.

StudentRecord.h

#ifndef STUDENTRECORD_H
#define STUDENTRECORD_H
class StudentRecord{
	char* m_firstName;
	char* m_lastName;
	unsigned int m_id;
	float m_mark;
public:
	StudentRecord();
	StudentRecord(char*,char*,unsigned int,float);
	StudentRecord(StudentRecord&);
	~StudentRecord();
	StudentRecord& operator=(StudentRecord&);
	bool operator>(StudentRecord&);
	bool operator<(StudentRecord&);
	void Report();
	char* GetFirstName(){return m_firstName;}
	char* GetLastName(){return m_lastName;}
	unsigned int GetID(){return m_id;}
	float GetMark(){return m_mark;}
};
#endif

StudentRecord.cpp

#include <iostream>
#include "StudentRecord.h"
using namespace std;
StudentRecord::StudentRecord(){			// Default constructor

	m_firstName = NULL;
	m_lastName = NULL;
	m_id = 0;
	m_mark = 0.00;
}
StudentRecord::StudentRecord(char* first,char* last,unsigned int id,float mark){	// Overloaded constructor
	m_firstName = strcpy(new char[strlen(first)+1],first);
	m_lastName = strcpy(new char[strlen(last)+1],last);
	m_id = id;
	m_mark = mark;
}
StudentRecord::StudentRecord(StudentRecord& ref){		// Copy constructor
	*this = ref;
}
StudentRecord::~StudentRecord(){		// Destructor
	delete[] m_firstName;
	delete[] m_lastName;
}
StudentRecord& StudentRecord::operator=(StudentRecord& ref){	// Overloaded = operator
	m_firstName = ref.m_firstName;
	m_lastName = ref.m_lastName;
	m_id = ref.m_id;
	m_mark = ref.m_mark;

	return *this;
}
bool StudentRecord::operator>(StudentRecord& ref){		// Overloaded > operator
	if(m_mark > ref.m_mark)
		return true;
	else
		return false;
}
bool StudentRecord::operator<(StudentRecord& ref){		// Overloaded < operator
	if(m_mark < ref.m_mark)
		return true;
	else
		return false;
}
void StudentRecord::Report(){		// Print class members
	cout<<m_firstName<<"  "<<m_lastName<<"  "<<m_id<<"  "<<m_mark<<endl;
}

StudentDatabase.h

#include "StudentRecord.h"

#ifndef STUDENTDATABASE_H
#define STUDENTDATABASE_H

class StudentDatabase{
	char* m_DatabaseName;
	StudentRecord** m_ppRecords;
	unsigned int m_numRecords;
	char* m_FileName;
public:
	StudentDatabase();
	~StudentDatabase();
	bool OpenFile(void);
	void Report(void);
	void AddRecord(void);
	void DeleteRecord(void);
	void HighestMark(void);
	void LowestMark(void);
};
#endif

StudentDatabase.cpp

#include <iostream>
#include <fstream>
#include "StudentDatabase.h"

using namespace std;

StudentDatabase::StudentDatabase(){
	m_ppRecords = new (StudentRecord*);
	m_numRecords = 0;
}
StudentDatabase::~StudentDatabase(){
	delete[] m_ppRecords;
}
bool StudentDatabase::OpenFile(void){
	char fName[50],lName[50],FileName[140];		// Temporary variables for first and last name
	unsigned int id;							// Temporary variable for id
	float grade;					// Temporary varialbe for mark
	ofstream out;					// File output stream
	ifstream in;					// File input stream

	if(m_ppRecords == NULL)			// Make sure the array memory is allocated
		return false;

	cout<<"OPEN FILE\n";
	cout<<"Please enter the name of the file to open: ";
	
	cin>>FileName;
	m_FileName = new char(sizeof(FileName));
	strcpy(m_FileName,FileName);

	in.open(m_FileName,fstream::in);				// Get the file name then open try to open the file
	
	if(in.is_open()){							// Check if the file is opened 
		while(in>>fName>>lName>>id>>grade){		// Get input from the file then assign it to the record
			m_ppRecords[m_numRecords] = (new StudentRecord(fName,lName,id,grade));
			m_numRecords++;
		}
		cout<<"READIN RECORDS INTO MEMORY\n";
		cout<<"There are "<<m_numRecords<<" student records.\n";
	}
	else{						// Create the file if it's not opened
		in.close();
		in.clear();
		out.open(m_FileName);
		out.close();
		in.open(m_FileName);
		if(in.is_open()){
			cout<<"Opening file for 1st time\n";
			cout<<"READIN RECORDS INTO MEMORY\n";
			cout<<"There are "<<m_numRecords<<" student records.\n";
		}
		else
			return false;			// Error creating the file 
	}
	in.close();
	return true;
}
void StudentDatabase::Report(void){
	for(unsigned int i=0;i<m_numRecords;i++){
		cout<<"Record #"<<i<<endl;
		m_ppRecords[i]->Report();
	}
}
void StudentDatabase::AddRecord(void){
		char fName[50],lName[50];				// Temp variables for first and last name
		unsigned int id;									// Temp variable for id
		float grade;							// Temp variable for mark
		int getInput = 1;						// Used to end the while loop for input
		bool bFailed = true;						// Used to stop input on error

		while(getInput){			// Start getting input
			cout<<"Please enter first name:\n";
			cin>>fName;		// Get first name input
			if(!cin.good()){					// Check if there's an error during input
				cout<<"Error getting input\n";	//Used each time the user is asked for input 
				bFailed = cin.fail();
				cin.clear();
				cin.ignore(128,'\n');
				break;
			}
			cout<<"Please enter last name:\n";
			cin>>lName;		// Get last name input
			if(!cin.good()){
				cout<<"Error getting input\n";
				bFailed = cin.fail();
				cin.clear();
				cin.ignore(128,'\n');
				break;
			}
			cout<<"Please enter ID:\n";
			cin>>id;		// Get id input
			if(!cin.good()){
				cout<<"BAD ID INPUT\n";
				bFailed = cin.fail();
				cin.clear();
				cin.ignore(128,'\n');
				break;
			}
			cout<<"Please enter mark:\n";
			cin>>grade;		// Get mark input
			if(!cin.good()){
				cout<<"BAD MARK INPUT\n";
				bFailed = cin.fail();
				cin.clear();
				cin.ignore(128,'\n');
				break;
			}

			getInput = 0;
		}
		if(bFailed==true){		// If input didn't fail assign the values to the record
			m_ppRecords[m_numRecords] = (new StudentRecord(fName,lName,id,grade));
			m_numRecords++;
			cout<<"Number of Records = "<<m_numRecords<<endl;
			cout<<"ADDED A NEW RECORD IN MEMORY OK"<<endl;
		}

}
void StudentDatabase::DeleteRecord(void){
	delete m_ppRecords[m_numRecords];
	m_numRecords--;
}
void StudentDatabase::HighestMark(void){
	int id_Highest = 0;

	for(int i=0;i<m_numRecords;i++){
		if(m_ppRecords[id_Highest]<m_ppRecords[i])
			id_Highest = m_ppRecords[i]->GetID();
	}
	m_ppRecords[id_Highest]->Report();
}
void StudentDatabase::LowestMark(void){
	int id_Lowest = 0;

	for(int i=0;i<m_numRecords;i++){
		if(m_ppRecords[id_Lowest]<m_ppRecords[i])
			id_Lowest = m_ppRecords[i]->GetID();
	}
	m_ppRecords[id_Lowest]->Report();
}

The problem is that you are not doing a deep copy of your object. Your assignment operator performs a shallow copy (copy only the pointer, you don't copy the memory it points to). I suggest you read my tutorial on resource-holding classes and RAII. Your copy-constructor is also wrong, I highly recommend that you use a copy-and-swap idiom, like I recommend in my tutorial.

This article has been dead for over six months. Start a new discussion instead.