У меня есть класс, содержащий указатель члена, который динамически размещается в его конструкторе следующим образом:
class Record {
public:
Record(unsigned short numBytes, char* bufRecord);
~Record();
unsigned short size() {return m_numBytes;}
private:
unsigned short m_numBytes;
char* m_bufRecord;
};
Record::Record(unsigned short numBytes, char* bufRecord) {
m_numBytes = numBytes;
m_bufRecord = new char[numBytes];
for(unsigned short i=0; i<numBytes; i++)
m_bufRecord[i] = bufRecord[i];
}
Record::~Record() {
delete m_bufRecord;
}
Он в основном копирует входной буфер в динамически распределяемый буфер члена. Я перехожу к использованию этого класса следующим образом в конструкторе другого класса:
class File {
public:
File(const char* fileName);
~File();
unsigned int numRecords() {return m_records.size();}
Record getRecord(unsigned int numRecord) {return m_gdsRecords[numRecord];}
private:
std::ifstream m_file;
std::vector<Record> m_records;
};
File::File(const char* fileName) : m_file(fileName, ios::in | ios::binary) {
while(!m_file.eof()) {
char bufNumBytes[2];
char* bufRecord;
unsigned short numBytes;
m_file.read(bufNumBytes, 2);
numBytes = (bufNumBytes[0] << 8) + bufNumBytes[1] - 2;
bufRecord = new char[numBytes];
m_file.read(bufRecord, numBytes);
Record record(numBytes, bufRecord);
m_records.push_back(record);
delete bufRecord;
}
}
Однако, когда я создаю экземпляр этого класса, я получаю следующую ошибку, которая, кажется, утверждает, что я дважды освобождаю m_bufRecord
:
*** Error in `./a.out': double free or corruption (fasttop): 0x0000000001cb3280 ***
Я предполагаю, что проблема заключается в вставке класса, содержащего указатель на vector
элемент, и деструктор вызывается дважды по одному и тому же указателю, но я не уверен, как это происходит. Что я здесь не так делаю?
Это случай Правило трех. Если вашему классу необходимо освободить ресурсы в деструкторе, ему, как правило, необходимо объявить конструктор копирования (и оператор назначения копирования), чтобы либо скопировать принадлежащий ресурс, либо управлять общим владением, либо предотвратить копирование.
Record getRecord(unsigned int numRecord) {return m_gdsRecords[numRecord];}
Эта функция возвращает копию Record
, Итак, теперь у вас есть два Record
с тем же m_bufRecord
указатель. Запуск деструкторов на этих Record
s попытается удалить одно и то же значение указателя дважды.