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