C++手写无STL容器电话簿程序触发断点错误求助
解决PhoneBook.exe触发断点的问题
嘿,我帮你排查了代码里的几个关键问题,其中最致命的那个直接导致了断点触发,咱们一步步拆解修复:
1. 核心致命问题:PhoneBook构造函数的内存分配顺序错误
看你PhoneBook的构造函数代码:
PhoneBook::PhoneBook(string pbFileName, int pbSize) { fileName = pbFileName; contacts = new Person[size]; // 这里size还没赋值!是随机垃圾值 size = pbSize; currentSize = 0; }
你居然在给size赋值之前,就用它来分配contacts数组的内存!这时候size是未初始化的随机值,分配出来的内存要么太小要么超大,直接触发内存错误。赶紧调换顺序,先给size赋值再分配内存:
PhoneBook::PhoneBook(string pbFileName, int pbSize) { fileName = pbFileName; size = pbSize; // 先把size初始化好 contacts = new Person[size]; currentSize = 0; }
2. Person拷贝构造函数的无意义操作
你的Person拷贝构造函数一上来就delete成员变量,但此时刚创建的对象,firstName这些指针都是nullptr啊!虽然delete空指针是合法的,但完全没必要,还容易让人误解逻辑:
Person::Person(Person & p) { // 刚创建的对象,这些指针都是空的,delete它们纯属多余 delete[] firstName; delete[] lastName; delete[] nickName; delete[] address; delete[] workPhone; delete[] privatePhone; // ... 后面的赋值逻辑 }
修复方案:直接删掉开头的delete语句,直接为新对象分配内存并拷贝内容就行:
Person::Person(Person & p) { firstName = new char[strlen(p.firstName) + 1]; lastName = new char[strlen(p.lastName) + 1]; nickName = new char[strlen(p.nickName) + 1]; address = new char[strlen(p.address) + 1]; workPhone = new char[strlen(p.workPhone) + 1]; privatePhone = new char[strlen(p.privatePhone) + 1]; stringcpy(firstName, p.firstName); stringcpy(lastName, p.lastName); stringcpy(nickName, p.nickName); stringcpy(address, p.address); stringcpy(workPhone, p.workPhone); stringcpy(privatePhone, p.privatePhone); }
3. stringcpy函数的小缺陷
你的stringcpy在循环里每次都把destination[i+1]设为'\0',虽然最终结果是对的,但效率低,而且如果传入空字符串会有隐患。改成标准写法,先拷贝所有字符,最后统一加终止符:
char* stringcpy(char* destination, const char* source) { int i = 0; while (source[i] != '\0') { destination[i] = source[i]; i++; } destination[i] = '\0'; // 最后一次性加终止符,更高效安全 return destination; }
4. removePerson的逻辑bug
你的removePerson函数有两个问题:一是找到匹配项后没跳出循环,二是不管有没有找到联系人都减currentSize,这会导致计数错误:
void PhoneBook::removePerson(Person p) { for (size_t i = 0; i < currentSize; i++) { if (contacts[i] == p) { // 把i后面的元素往前移一位,注意循环到currentSize-1就行 for (size_t j = i; j < currentSize - 1; j++) { contacts[j] = contacts[j + 1]; } currentSize--; break; // 找到后立刻跳出,避免重复处理 } } // 别在这里减currentSize!没找到的话会错误减少计数 }
5. printPhoneBook的循环问题
你的printPhoneBook循环条件是i < currentSize - 1,这会漏掉最后一个联系人,而且只打印firstName,信息太不全了,改成这样:
void PhoneBook::printPhoneBook() { for (size_t i = 0; i < currentSize; i++) { cout << "联系人 " << i+1 << ":" << endl; cout << "姓名:" << contacts[i].firstName << " " << contacts[i].lastName << endl; cout << "昵称:" << contacts[i].nickName << endl; cout << "地址:" << contacts[i].address << endl; cout << "工作电话:" << contacts[i].workPhone << endl; cout << "私人电话:" << contacts[i].privatePhone << endl; cout << "-------------------------" << endl; } }
额外提醒
- 记得在
Person.cpp里包含<cstring>头文件,因为你用到了strlen和strcmp,不然可能会有编译警告或者错误。 - 可以考虑在Person的构造函数里加个判断,防止传入nullptr字符串导致
strlen(nullptr)崩溃。
把这些修复完之后,重新编译运行,断点问题应该就彻底解决了。
内容的提问来源于stack exchange,提问作者dinci11
相关产品推荐
相关产品推荐

