You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:52:39