[C++]filesystem内存访问问题?

新手上路,请多包涵

我自写了三个头文件QC,writefiles,QFunction
QC.hpp

#include <QtWidgets/qwidget.h>
#include <QtCore/qtextcodec.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qstring.h>
#include <String>
#include <vector>
#include <iostream>
#include <QtWidgets/qmessagebox.h>
class QC {
public:
    std::vector<QString> contents;
    QC(const std::vector<std::string>& content) {
    for (auto indexcontent : content) {
        QTextCodec* Codec = QTextCodec::codecForName("GBK");
        QString Qcontent = Codec->toUnicode(indexcontent.c_str());
    contents.push_back(Qcontent);
    }
    }
};
inline void SHOWERROR(QString content) {
    QMessageBox::warning(nullptr, "error", content);
}


inline ::QString QCT(const char* content) {
        QTextCodec* Codec = QTextCodec::codecForName("GBK");
        QString Qcontent = Codec->toUnicode(content);
        return Qcontent;
    }
inline QStringList QCTLT(std::vector<const char*>& vcc) {
    QStringList  Result;
    for (const auto& content : vcc) {
        Result.append(QCT(content));
    }
    return Result;
}
inline QString SingleQRB(QString& qc,char tar) {
    int check = 0;
    //check
    for (auto& qcr : qc) {
        if (qcr == tar) {
            check += 1;
        }
    }
    if (check == 1) {
    QString Result(QCT(""));
    QString middle(QCT(""));
    bool if_(true);
    for (auto& per : qc) {
        if (per != tar and if_) {
            Result += per;
        }
        else if (per == tar) { Result = per + Result; if_ = false; }
        else  {
            middle += per;
        }
    }
    Result = middle + Result;
    return Result;}
    else {
        QChar qc(tar);
        QString response1 = QCT("Repeating \"") + tar + QCT("\"") + QCT(" or no \"") + tar + QCT("\"");
        QString response2 = QCT("SingleQRB accepts a QString just includes one \"") + tar + QCT("\"");
        QMessageBox::information(nullptr,response1 , response2);
        return 0;
    }

}

writefiles.hpp

#include <fstream>
#include <windows.h>
#include <vector>

inline void WriteCover(const char* path, const char* content) {
    std::ofstream ofile(path);
    if (ofile.is_open()) {
        ofile << content;
        ofile.close();
    }
    else {
        MessageBoxA(NULL, "文件打开失败", "打开文件", MB_ICONEXCLAMATION);
    }
}

inline void WriteAdd(const char* path, const char* content) {
    std::ofstream ofile(path, std::ios::app);
    if (ofile.is_open()) {
        ofile << content;
        ofile.close();
    }
    else {
        MessageBoxA(NULL, "文件打开失败", "打开文件", MB_ICONEXCLAMATION);
    }
}

inline std::string ReadAll(const char* path) {
    std::ifstream ifile(path);
    if (ifile.is_open()) {
        std::string content;
        char perchar;
        while (ifile.get(perchar)) {
            content += perchar;
        }
        ifile.close();
        return content;
    }
    else {
        MessageBoxA(NULL, "文件打开失败", "打开文件", MB_ICONEXCLAMATION);
    }
    return "";
}

inline std::string ReadCustom(const char* path, int top, int end) {
    std::ifstream ifile(path);
    if (ifile.is_open()) {
        std::vector<char> content;
        std::string CharContent;
        char perchar;
        while (ifile.get(perchar)) {
            content.push_back(perchar);
        }
        if (top <= end) {
            if (end > content.size()) {
                MessageBoxA(NULL, "读取错误,右索引值过大", "读取文件", MB_ICONEXCLAMATION);
            }
            else if (top < 0) {
                MessageBoxA(NULL, "读取错误,左索引值过小", "读取文件", MB_ICONEXCLAMATION);
            }
            else {
                for (; top <= end; top++) {
                    CharContent += content[top];
                }
                return CharContent;
            }
        }
        else {
            MessageBoxA(NULL, "读取错误,请检查索引值", "读取文件", MB_ICONEXCLAMATION);
        }
    }
    else {
        MessageBoxA(NULL, "文件读取失败", "读取文件", MB_ICONEXCLAMATION);
    }
    return "";
}

QFunction.hpp

#include <QtWidgets/qpushbutton.h>
#include <functional>
#include <utility>
namespace QButton {
    template <typename Func, typename... Args>
    inline void connect(QPushButton* button, Func f, Args&&... args) {
        QObject::connect(button, &QPushButton::clicked, [f, args...]() {
            f(args...);
            });
    }
}
namespace QCBox {
    template <typename Func, typename... Args>
    inline void ClickedConnect(QComboBox* combobox, Func f, Args... args) {
        QObject::connect(combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), [=](int index) {f(args...); 
            });
    }
}

我的源文件

#include <QtWidgets/qwidget.h>
#include <windows.h>
#include <QtWidgets/qapplication.h>
#include <QtWidgets/qlabel.h>
#include <QtWidgets/qframe.h>
#include <QtWidgets/qlineedit.h>
#include <QtCore/qtextcodec.h>
#include <QtWidgets/QVBoxLayout>
#include <QtWidgets/QPushButton>
#include <QtWidgets/qcombobox.h>
#include <QtGui/qfont.h>
#include <QtCore/qstringlist>
#include <QtCore/qstring.h>
#include <QtGui/qpixmap.h>
#include <QtGui/qicon.h>
#include <QtWidgets/qtextedit.h>
#include <QtWidgets/qmessagebox.h>
#include "QFunction.hpp"
#include "writefiles.hpp"
#include <filesystem>
#include "QC.hpp"
#define Button QPushButton
#define Label QLabel
#define QHBox QHBoxLayout
#define QVBox QVBoxLayout


void change(QComboBox* combo, QTextEdit* text) {
    if (combo->currentText() == QCT("追加")) {
        text->setPlaceholderText(QCT("输入要追加的内容"));
    }
    else {
        text->setPlaceholderText(QCT("输入新的内容"));
    }
}
void writeinto(QComboBox* combo, QLineEdit* line, QTextEdit* text) {
    if (combo->currentText() == QCT("追加")) {
        std::string filePath = line->text().toStdString();
        std::string content = text->toPlainText().toStdString();
        if (std::filesystem::exists(filePath)) {
            WriteAdd(filePath.c_str(), content.c_str());
            QMessageBox::information(nullptr, QCT("追加"), QCT("追加内容成功"));
        }
        else {
            QMessageBox::information(nullptr, QCT("路径错误"), QCT("请输入正确的文件路径"));
        }
    }
    else {
        std::string filePath = line->text().toStdString();
        std::string content = text->toPlainText().toStdString();
        if (std::filesystem::exists(filePath)) {
            WriteCover(filePath.c_str(), content.c_str());
            QMessageBox::information(nullptr, QCT("覆盖"), QCT("内容覆盖成功"));
        }
        else {
            QMessageBox::information(nullptr, QCT("路径错误"), QCT("请输入正确的文件路径"));
        }
    }
}
// WinMain 入口函数 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {
    int argc = 0;
    char** argv = nullptr;
    QApplication app(argc, argv);//应用程序类
    QWidget mainwindow;  //主窗口类
    mainwindow.setWindowTitle(QCT("文本内容追加"));
    mainwindow.resize(600, 500);
    QFont font("Afrail", 15);
    //组件
    QTextEdit* text = new QTextEdit(&mainwindow);
    QComboBox* combo = new QComboBox(&mainwindow);
    QLineEdit* line = new QLineEdit(&mainwindow);
    Button* button = new Button(QCT("Write Into"), &mainwindow);
    QVBox* vbox = new QVBox(&mainwindow);
    text->setFont(font);
    line->setFont(font);
    combo->setFont(font);
    combo->addItems({ QCT("追加"), QCT("覆盖") });
    line->setPlaceholderText(QCT("文件路径"));
    text->setPlaceholderText(QCT("输入要追加的内容"));
    vbox->addWidget(combo);
    vbox->addWidget(line);
    vbox->addWidget(text);
    vbox->addWidget(button);
    QButton::connect(button, writeinto, combo, line, text);
    QCBox::ClickedConnect(combo, change, combo, text);
    //显示窗口 
    mainwindow.show();
    return app.exec();
}

运行成功,但当我点击writeinto按钮时
出现内存访问的问题

我询问过许多AI包括Deepseek,但错误依旧在! 我打算使用QFile重写,但对于这个问题我依旧想得到解决

阅读 508
avatarAI BotBETA

回答

内存访问问题通常是由于访问了未初始化或已释放的内存导致的。在你的代码中,可能的问题源包括以下几个方面:

  1. 字符串编码转换
    你的代码中使用了 QTextCodec 进行字符串编码转换,确保所有转换的字符串在转换前是有效的,并且转换后的字符串被正确处理和存储。
  2. Lambda 捕获方式
    QButton::connectQCBox::ClickedConnect 函数中,你使用了 lambda 表达式来连接信号和槽。这里需要注意捕获列表的使用。在你的 writeinto 函数中,lambda 使用了 [=] 捕获方式,这意味着所有变量都是通过值捕获的。对于 QComboBox* combo, QLineEdit* line, QTextEdit* text 这样的指针,值捕获通常没问题,但要确保这些指针在 lambda 表达式执行期间仍然有效。
  3. 文件路径和内容处理
    确保 line->text().toStdString()text->toPlainText().toStdString() 返回的字符串是有效的,并且文件路径正确无误。如果文件路径包含非法字符或指向一个不可访问的位置,std::filesystem::exists 可能会表现异常。
  4. 文件操作
    WriteCoverWriteAdd 函数中,你使用了 std::ofstream 进行文件写操作。确保在文件打开失败时能够正确处理错误,并且文件内容没有超出预期的范围。
  5. 未捕获的异常
    检查代码中是否有未被捕获的异常,特别是在文件操作和字符串处理部分。虽然 C++ 标准库通常不会抛出异常用于文件操作失败(而是返回错误码),但确保你的代码逻辑能够处理所有可能的错误情况。
  6. 资源泄露
    虽然这个问题不直接导致内存访问错误,但长期运行可能会导致内存问题。确保所有动态分配的资源(如 QTextCodec 对象)在使用完毕后得到适当释放。

针对你提到的内存访问问题,以下是一些具体的建议:

  • 检查指针有效性:确保所有使用的指针(如 combo, line, text)在 lambda 表达式执行时仍然有效。如果这些对象有可能在 lambda 执行前被销毁,考虑使用智能指针或改变捕获方式(例如使用 [&] 捕获外部作用域的所有变量引用)。
  • 添加错误检查:在文件操作前后添加更多的错误检查,确保文件正确打开和关闭。
  • 使用调试工具:使用调试工具(如 GDB 或 Visual Studio Debugger)来运行你的程序,并在内存访问错误发生时检查调用堆栈和变量状态。
  • 简化问题:尝试创建一个最小化的示例,只包含导致问题的部分代码,这有助于快速定位问题。

如果问题依旧存在,考虑重写文件操作部分,使用 Qt 提供的 QFile 类而不是标准库的 std::ofstream,因为 QFile 类更好地集成了 Qt 的事件系统和内存管理机制。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Microsoft
子站问答
访问
宣传栏