From 9ca199497985c526c31e8884f6911fd49be6b807 Mon Sep 17 00:00:00 2001 From: shiyb <ninthozward1@outlook.com> Date: 星期一, 19 五月 2025 17:07:39 +0800 Subject: [PATCH] Merge branch 'master' of ssh://117.78.1.188:29418/test-upload 修改了错误示例 --- Test/errorexample.cpp | 267 +++++++++++++++++++++++++++++++++++++++-------------- 1 files changed, 195 insertions(+), 72 deletions(-) diff --git a/Test/errorexample.cpp b/Test/errorexample.cpp index e3c828a..0cd7a52 100644 --- a/Test/errorexample.cpp +++ b/Test/errorexample.cpp @@ -1,105 +1,228 @@ #include "errorexample.h" +#include <QFile> #include <QLabel> +#include <QPushButton> errorexample::errorexample() { // 1.未包含必要的头文件 // 错误:缺少 #include <QLabel> QLabel label("Hello"); // 编译错误:'QLabel' was not declared in this scope label.show(); - // 2.未初始化指针 - QLabel *label4; - label4->setText("Hello"); // 错误:使用未初始化的指针 + //-----------指针常见问题--------------- - // 修复:初始化指针 - QLabel *label5 = new QLabel; + //①空指针解引用 + QWidget *widget = nullptr; + widget->show(); //对值为nullptr的指针进行访问操作,会引发崩溃 - // 3.父对象管理不当导致内存泄露 - QLabel *label1 = new QLabel("Memory Leak"); - label1->show(); + //解决办法: + QWidget *widget1 = nullptr; + if (widget1) { //使用指针前,先确认其是否为nullptr + widget1->show(); + } - // 正确做法:设置父对象,Qt会自动管理内存 + //②野指针 + //指针所指向的内存已经被释放,但后续仍在使用该指针 + QWidget *widget2 = new QWidget; + delete widget2; + widget2->show(); //此时widget2已经变成野指针 + + //解决办法: + //对象释放之后,及时将指针置为nullptr(利用 Qt + //对象的父子关系机制来自动管理内存) + QWidget *widget3 = new QWidget; + delete widget3; + widget3 = nullptr; //避免野指针 + + //③内存泄露:未释放动态分配的内存 + void createLeak() { + int *ptr = new int(10); //分配后未释放 + } + //解决办法: + void createLeak() { + int *ptr = new int(10); //分配后未释放 + delete ptr; + ptr = nullptr; + } + + //④父子关系误用 QWidget *parent = new QWidget; - QLabel *managedLabel = new QLabel("Managed", parent); + QPushButton *button = new QPushButton(parent); + delete button; // 手动删除子对象 + delete parent; // 崩溃!父对象试图再次删除已释放的 button - // 4.使用已删除的对象 - QLabel *label2 = new QLabel("Delete Me"); - delete label2; + //解决办法:依赖对象树自动管理 + QWidget *parent2 = new QWidget; + QPushButton *button2 = new QPushButton(parent); + delete parent2; // 自动删除所有子对象(包括 button) - // 错误:访问已删除的对象 - label2->setText("Oops"); // 未定义行为 + //⑤智能指针与对象树冲突 + //混合使用父对象和智能指针 + QWidget *parent3 = new QWidget; + // 错误:父对象已管理 button,智能指针会导致双重释放 + std::unique_ptr<QPushButton> button3(new QPushButton(parent)); - // 5.字符串编码问题 - QLabel *label3 = new QLabel; - // 错误:硬编码非ASCII字符串 - label3->setText("中文文本"); // 可能显示乱码,取决于源文件编码 + //解决办法1:仅用父对象管理 + QWidget *parent4 = new QWidget; + QPushButton *button4 = new QPushButton(parent4); // 父对象负责释放 - // 正确做法:使用tr()进行翻译 - label3->setText(tr("中文文本")); + //解决办法2:无父对象时使用智能指针 + std::unique_ptr<QPushButton> button5 = std::make_unique<QPushButton>(); - // 6.容器越界访问 - QList<int> list = {1, 2, 3}; - - // 错误:越界访问 - int value = list[3]; // 索引最大为2 - - // 正确做法:使用at()并检查边界 - if (list.size() > 3) { - int safeValue = list.at(3); // at()会在越界时抛出异常 + //⑥容器中的指针管理 + // 忘记释放files数组及其中的指针所指向的内存 + QFile *files = new QFile[10]; + for (int i = 0; i < 10; ++i) { + files[i].setFileName("file" + QString::number(i)); } - // 7.缺失终止条件的For循环 - for (int i = 0;; i++) { // 错误:无终止条件 - //循环体 + //解决办法: + QFile **files1 = new QFile *[10]; + for (int i = 0; i < 10; ++i) { + files[i].setFileName("file" + QString::number(i)); + } + for (int i = 0; i < 10; ++i) { + delete files1[i]; + } + delete[] files; + + //-----------常见逻辑错误--------------- + + //①无限循环 + //错误:(无终止条件) + for (int i = 0; i < 10;) { + qDebug() << "Looping..."; + // 忘记写i++ } - // 正确写法: - for (int i = 0; i < 10; i++) { // 添加终止条件 - //循环体 + //错误:死循环(条件恒为真) + while (true) { + //代码块 未提供退出机制 } - // 8.误用 = 代替 == - if (x = 5) { // 误将赋值操作当作比较,条件始终为 true(除非 x 是布尔类型) - // ... + //解决办法 + // 增加i++ + for (int i = 0; i < 10; i++) { + qDebug() << "Looping..." << i; } - // 9.事件处理未调用基类实现 - void CustomWidget::paintEvent(QPaintEvent * event) { - // 错误:未调用基类实现 - QPainter painter(this); - // 缺少:QWidget::paintEvent(event); + //使用break或return退出循环 + while (true) { + if (data.isEmpty()) break; // 条件满足时退出 } - // 10.信号槽参数不匹配 - // 错误:信号参数与槽参数类型不匹配 - connect(sender, &Sender::valueChanged(int), receiver, - &Receiver::updateValue(QString)); + //②数据/容器越界访问 + // 错误:访问越界(索引0~9,但循环到i=10) + QVector<int> numbers(10); + for (int i = 0; i <= 10; ++i) { // 应为i < 10 + numbers[i] = i; // i=10时越界 + // 错误:使用空容器 + QStringList names; + qDebug() << names[0]; // 访问空容器的第一个元素 - // 修复:确保参数类型一致 - connect(sender, &Sender::valueChanged(int), receiver, - &Receiver::updateValue(int)); + //解决办法 + //使用安全的访问方法(如at()代替[]) + qDebug() << numbers.at(10); + //检查容器是否为空 + if (!names.isEmpty()) { + qDebug() << names[0]; + } - // 11.未实现纯虚函数 - class MyInterface { - public: - virtual void pureVirtual() = 0; - }; + // 2.未初始化指针 + QLabel *label4; + label4->setText("Hello"); // 错误:使用未初始化的指针 - class MyClass : public MyInterface { - // 错误:未实现纯虚函数 - }; + // 修复:初始化指针 + QLabel *label5 = new QLabel; - // 修复:实现纯虚函数 - void MyClass::pureVirtual() { /* 实现 */ + // 3.父对象管理不当导致内存泄露 + QLabel *label1 = new QLabel("Memory Leak"); + label1->show(); + + // 正确做法:设置父对象,Qt会自动管理内存 + QWidget *parent = new QWidget; + QLabel *managedLabel = new QLabel("Managed", parent); + + // 4.使用已删除的对象 + QLabel *label2 = new QLabel("Delete Me"); + delete label2; + + // 错误:访问已删除的对象 + label2->setText("Oops"); // 未定义行为 + + // 5.字符串编码问题 + QLabel *label3 = new QLabel; + // 错误:硬编码非ASCII字符串 + label3->setText("中文文本"); // 可能显示乱码,取决于源文件编码 + + // 正确做法:使用tr()进行翻译 + label3->setText(tr("中文文本")); + + // 6.容器越界访问 + QList<int> list = {1, 2, 3}; + + // 错误:越界访问 + int value = list[3]; // 索引最大为2 + + // 正确做法:使用at()并检查边界 + if (list.size() > 3) { + int safeValue = list.at(3); // at()会在越界时抛出异常 + } + + // 7.缺失终止条件的For循环 + for (int i = 0;; i++) { // 错误:无终止条件 + //循环体 + } + + // 正确写法: + for (int i = 0; i < 10; i++) { // 添加终止条件 + //循环体 + } + + // 8.误用 = 代替 == + if (x = 5) { // 误将赋值操作当作比较,条件始终为 true(除非 x 是布尔类型) + // ... + } + + // 9.事件处理未调用基类实现 + void CustomWidget::paintEvent(QPaintEvent * event) { + // 错误:未调用基类实现 + QPainter painter(this); + // 缺少:QWidget::paintEvent(event); + } + + // 10.信号槽参数不匹配 + // 错误:信号参数与槽参数类型不匹配 + connect(sender, &Sender::valueChanged(int), receiver, + &Receiver::updateValue(QString)); + + // 修复:确保参数类型一致 + connect(sender, &Sender::valueChanged(int), receiver, + &Receiver::updateValue(int)); + + // 11.未实现纯虚函数 + class MyInterface { + public: + virtual void pureVirtual() = 0; + }; + + class MyClass : public MyInterface { + // 错误:未实现纯虚函数 + }; + + // 修复:实现纯虚函数 + void MyClass::pureVirtual() { /* 实现 */ + } + + // 12.未正确实现拷贝构造函数 + class MyClass1 { + public: + QWidget *widget; + MyClass1(const MyClass1 &other) { + widget = other.widget; + } // 错误:浅拷贝 + }; + + // 修复:深拷贝或禁用拷贝构造函数 + MyClass1(const MyClass1 &other) = delete; } - - // 12.未正确实现拷贝构造函数 - class MyClass1 { - public: - QWidget *widget; - MyClass1(const MyClass1 &other) { widget = other.widget; } // 错误:浅拷贝 - }; - - // 修复:深拷贝或禁用拷贝构造函数 - MyClass1(const MyClass1 &other) = delete; -} -- Gitblit v1.9.1