free(str);
str = NULL;05 易错陷阱:代码看着没红,不代表它安全
这页专门处理问答/改错题。答题套路固定:指出问题 → 说后果 → 给修改。
第36题
野指针:free 以后,指针不会自动变 NULL
char *str = (char *)malloc(100);
strcpy(str, "hello");
free(str);
if (str != NULL) {
strcpy(str, "world");
printf(str);
}
标准说法
free(str) 只释放 str 指向的内存,不会把 str 变量本身改成 NULL。str 还保存着旧地址,但那块内存已经不归你管了,所以 str 成为野指针。
| 代码 | 真实发生的事 | 考场怎么说 |
|---|---|---|
free(str); | 内存被还回去 | 释放后不能再用。 |
if (str != NULL) | 大概率仍然成立 | 这个判断没用,因为 str 没自动变 NULL。 |
strcpy(str, "world") | 往已释放内存写 | 结果不可预料,可能崩溃,可能看似正常。 |
✅ 修改
第37题
浅拷贝:两个对象指向同一块内存
题目场景:类中有指针成员
pFirstName,执行 Mike = John 时,如果没有自己重载赋值运算符,就会调用默认赋值函数,逐个成员直接复制。// 重点不是完整类定义,而是这个危险动作:
Person Mike("Mike", 25);
Person John("John", 30);
Mike = John; // 默认赋值:只复制指针地址,不复制指针指向的内容
人话翻译
默认赋值像“只复制快递单号”,不是重新买一份东西。结果 Mike 和 John 的指针都指向同一块姓名内存。
内存泄漏Mike 原来指向的内存没人释放了,像旧钥匙丢了,房子还占着。
双重释放两个对象析构时释放同一块内存,像同一张票退两次,后果不可预料。
✅ 解决
Person& Person::operator=(const Person& rhs) {
if (this == &rhs) return *this;
delete [] pFirstName;
pFirstName = new char[strlen(rhs.pFirstName) + 1];
strcpy(pFirstName, rhs.pFirstName);
return *this;
}
记法
类里有
char*、int* 这种自己管内存的指针,就想到:析构、拷贝构造、赋值运算符,三件套要一起管。
第41题
私有成员:外面不能直接碰
class Person {
public:
double getHeight() { return this->height; }
void setHeight(double height) { this->height = height; }
private:
double height;
};
int main() {
Person p;
p.height = 1.85; // 错
cout << p.getHeight();
}
✅ 修正
Person p;
p.setHeight(1.85);
cout << p.getHeight() << '\n';
考场说法
height 是 private 私有成员,只能在类内部直接访问。类外要通过 public 的 setter/getter 间接访问。
总背诵
改错题固定回答格式
第一句:这里有 bug,问题是……
第二句:原因是……,会导致……
第三句:修改方法是……