Debug小错记录

Debug记录

注:记录自己在编程时犯的各种错误,以便未来快速编程(不痛哭流涕)

c++之OOP

1. C风格内存分配与“+1”原则

  • 错误现象strcpy 报错、输出乱码、字符串末尾出现奇怪字符。

  • 错误根源:忽略了 C 风格字符串的结束符 \0

  • ⚠️ Debug 经验

    • 凡是使用 new char[len] 存储字符串,必须改为 new char[len + 1]

    • 在填充完字符后,务必手动封口:array[len] = '\0';

    • strlen只能处理有\0` 结尾的字符串,否则会因越界而返回错误长度。

2. 构造函数不能 delete!

  • 错误现象:程序刚运行就崩溃(Segmentation Fault)。

  • 错误根源:在构造函数(包括拷贝构造)里使用了 delete

  • Debug 经验

    • 构造函数是对象的“出生”,此时成员指针 array 里是随机垃圾值。绝对不能 delete 随机指针

    • 拷贝构造函数中,直接 new 即可;只有在 operator=(赋值运算符)中,才需要先 delete 旧内存。

    • 习惯在构造函数初始化列表中将指针置为 NULL

3. 赋值运算符(operator=)的“自杀”

  • 错误现象:执行 a = a 后,对象数据全部丢失或崩溃。

  • 错误根源:没有检查“自我赋值”。

  • Debug 经验

    • delete 自己的内存前,必须先判断 if (this == &other) return *this;

    • 忘记更新 length 成员:在拷贝 array 的同时,务必同步更新所有的元数据(如 length)。

4. 大数运算的“进位与对齐”

  • 错误现象:计算结果出现前导零(如 013)或进位丢失(如 9+1=0)。

  • 错误根源:逻辑过于复杂,进位(Carry)处理不统一。

  • Debug 经验

    • ⚠️ 统一存储方向:内部一律逆序存储array[0] 是个位),(正序拷贝,逆序输入)只有在 cout 时才倒序输出

    • 先算后存:先用一个 int 数组或足够大的临时 char 数组处理完所有的 sumcarry,最后再根据 carry 是否为 0 确定 length

    • 不要在循环内部直接改 length

一个关于加法参考:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
friend CHugeInt operator+(const CHugeInt &a, const CHugeInt &b) {
int maxl = a.length > b.length ? a.length : b.length;
char *tmp = new char[maxl + 2]; // 留出 1 位给进位,1 位给 \0

// 一个比较好的实现方式
int carry = 0;
for (int i = 0; i < maxl; i++) {
int moment = carry + (i >= a.length ? 0 : (a.array[i] - '0'))
+ (i >= b.length ? 0 : (b.array[i] - '0'));
tmp[i] = moment % 10 + '0';
carry = moment / 10;
}

int final_l = maxl;
if (carry > 0) {
tmp[final_l] = carry + '0';
final_l++;
}

// --- 关键修改点:手动封口 ---
tmp[final_l] = '\0';
// -------------------------

CHugeInt tt(final_l, tmp); // 这里的构造函数内部现在可以安全使用 strcpy 了
delete []tmp;
return tt;
}

// 关注:1.三目运算符的应用,补0
// 2.手动封口\0
// 3. carry 专门拿出来看(虽然不拿出来也行,但当时有未知错误,就是可能出现014等等多0现象,比较麻烦)
// 4.多开内存

5. 运算符重载的“返回类型”陷阱

  • 错误现象:加法结果无法传递,或者出现内存泄漏。

  • 错误根源operator+ 返回了局部变量的引用(CHugeInt&)。

  • Debug 经验

    • ⚠️ + 必须返回对象值CHugeInt),因为它产生的是一个临时的新值。

    • +=++(前置)必须返回**引用**(CHugeInt&),即return *this;`,以支持链式操作。

6. C 风格字符串与指针的“老派”脾气

  • 错误现象strcpy 拷贝结果不对。
  • 错误根源:数组名不能直接赋值,必须使用 memcpystrcpy
  • Debug 经验
  • 如果已经知道确切长度,memcpy 通常比 strcpy 更安全。
  • ⚠️ 在使用 tmp 数组中转后,记得 delete []tmp 释放临时空间,防止内存泄漏。