【发布时间】:2014-09-11 17:54:12
【问题描述】:
我正在清理我为一个使用 XCode 5 的课程编写的玩具程序。部分任务是熟悉动态内存分配(这意味着它必须使用 new 和 delete尽管没有它它真的可以正常工作)。我正在接收:
HeapOfStudents(67683,0x7fff769a6310) malloc: *** error for object 0x100300060: pointer being freed was not allocated *** set a breakpoint in malloc_error_break to debug
发生错误:
Student::~Student() {
delete firstName; // <- on this line
delete lastName;
delete address;
delete birthDate;
delete gradDate;
delete gpa;
delete crHours;
}
正在调用的...
int main() {
string line = "";
vector<Student> students;
//
//Create new students from file
//
ifstream data_file ("heapData");
if (data_file.is_open()) {
while(getline(data_file, line))
students.push_back(*new Student(line)); <- inside this call here
data_file.close();
}
else return 0;
完整的Student 类如下。
重要的是,我注意到虽然每个line 都被正确推送到向量,但当下一个Student 被推送时,前一个Student inside 向量被破坏。我总是在循环的第三次迭代中看到malloc 错误(文件有 50 行)。
如果我将vector<Student> 更改为vector<Student *> 并将student.push_back(*new Student(line)) 更改为student.push_back(new Student(line)),程序将无异常运行。
那么我的问题是:有人可以解释一下,在较低级别上,在这个循环中发生了什么会导致这个错误吗?
我的猜测是 *new Student(line) 每次都使用相同的指针,因此在每次迭代中,数据都会因为被释放而损坏(尽管这种解释引发了问题),而 new Student 每次都返回一个新指针,保留传递给students 的数据。我在想,也许我需要写一个拷贝构造函数……这只是我的猜测。
这是Student 类。 Address 和 Date 也是非常相似的自定义类。我没有包括它们,因为它们似乎不是问题的一部分。
//Constructors
Student::Student() {
firstName = new string("Testy");
lastName = new string("Testerson");
address = new Address("000 Street St", "", "Citytown", "State", "00000");
birthDate = new Date("01/02/9876");
gradDate = new Date("01/02/6789");
gpa = new string("10.0");
crHours = new string("300");
}
Student::Student(string FN, string LN, string L1, string L2, string C, string S, string Z, string BD, string GD, string GPA, string Hr) {
firstName = new string(FN);
lastName = new string(LN);
address = new Address(L1, L2, C, S, Z);
birthDate = new Date(BD);
gradDate = new Date(GD);
gpa = new string(GPA);
crHours = new string(Hr);
}
Student::Student(string line) {
set(line);
}
//Destructors
Student::~Student() {
delete firstName;
delete lastName;
delete address;
delete birthDate;
delete gradDate;
delete gpa;
delete crHours;
}
//Member Functions
void Student::set(string line) {
firstName = new string(line.substr(0, line.find_first_of(",")));
line = line.substr(line.find_first_of(",") + 1, string::npos);
lastName = new string(line.substr(0, line.find_first_of(",")));
line = line.substr(line.find_first_of(",") + 1, string::npos);
address = new Address();
address->setLine1(line.substr(0, line.find_first_of(",")));
line = line.substr(line.find_first_of(",") + 1, string::npos);
address->setLine2(line.substr(0, line.find_first_of(",")));
line = line.substr(line.find_first_of(",") + 1, string::npos);
address->setCity(line.substr(0, line.find_first_of(",")));
line = line.substr(line.find_first_of(",") + 1, string::npos);
address->setState(line.substr(0, line.find_first_of(",")));
line = line.substr(line.find_first_of(",") + 1, string::npos);
address->setZip(line.substr(0, line.find_first_of(",")));
line = line.substr(line.find_first_of(",") + 1, string::npos);
birthDate = new Date(line.substr(0, line.find_first_of(",")));
line = line.substr(line.find_first_of(",") + 1, string::npos);
gradDate = new Date(line.substr(0, line.find_first_of(",")));
line = line.substr(line.find_first_of(",") + 1, string::npos);
gpa = new string(line.substr(0, line.find_first_of(",")));
line = line.substr(line.find_first_of(",") + 1, string::npos);
crHours = new string(line.substr(0, line.find_first_of(",")));
line = line.substr(line.find_first_of(",") + 1, string::npos);
}
void Student::printReport() {
cout << *lastName << ", " << *firstName << ", " << address->getAddress()
<< ", " << birthDate->getDate() << ", " << gradDate->getDate()
<< ", " << *gpa << ", " << *crHours << endl;
}
void Student::printName() {
cout << *lastName << ", " << *firstName << endl;
}
string Student::getName() {
return string(*lastName + ", " + *firstName);
编辑以下是我为学生班编写的复制构造函数和赋值运算符,如果有人有兴趣查看/批评它们:
Student::Student(const Student & student){
firstName = new string(*student.firstName);
lastName = new string(*student.lastName);
address = new Address(*student.address);
birthDate = new Date(*student.birthDate);
gradDate = new Date(*student.gradDate);
gpa = new string(*student.gpa);
crHours = new string(*student.crHours);
}
Student& Student::operator=(const Student & student) {
return *new Student(student);
}
【问题讨论】:
-
你为什么还要在这里使用指针?只需将
firstName设为string而不是string *。 -
@cdhowie:见第一段。这是一个学习内存管理的练习。
-
在现代 C++ 中没有裸指针。
-
这段代码片段
*new Student(line)本质上是内存泄漏!new分配堆空间并返回一个(临时)指向它的指针。*运算符取消引用访问 Student 对象的指针。此时,您不再需要在delete语句中使用指针.. -
Rule of Three 违规。