You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复VS2019中C++的Debug Assertion Failure异常?

解决英越词典程序的Debug Assertion Failure异常

我编写了一款英越词典程序,功能包括添加带越南语释义的英文单词、基于本地文本文件(EN.txt、VN.txt等)翻译单词,以及先添加无释义单词后续补全释义。VS2019编译无报错,但调试时触发了Debug Assertion Failure异常,程序代码如下:

#include <iostream>
#include <fstream>
#include <string>
#include <io.h>
#include <fcntl.h>
#include <stdio.h>
#include <codecvt>
#include <locale>
#pragma warning (disable:4996)
using namespace std;

int main() {
    FILE* fd;
    fd = fopen("VN.txt", "a");
    int ngu, dumb;
    ngu = _setmode(_fileno(stdin), _O_U8TEXT);
    dumb =_setmode(_fileno(fd), _O_U8TEXT);
    locale loc(locale(), new codecvt_utf8<wchar_t>);
    wifstream out(L"VN.txt");
    fstream ENi("EN.txt", ios::in);
    fstream ENo("EN.txt", ios::app);
    fstream ENi2("EN2.txt", ios::in);
    fstream ENo2("EN2.txt", ios::app);
    fstream so("Num.txt", ios::in);
    int num;
    so >> num;
    int quit = 0;
    char EN[100];
    wchar_t VN[100];
    while (quit != 5) {
        cout << "Pick a number:" << endl;
        cout << "1. Add a word" << endl;
        cout << "2. Translate a word using data from this program" << endl;
        cout << "3. Add the missing meaning for a word" << endl;
        cout << "4. Test your memory with random words from this dictionary" << endl;
        cout << "5. Exit" << endl;
        cin >> quit;
        switch (quit) {
        case 1: {
            cout << "Please type the word you want to add:" << endl;
            cin.getline(EN, 100);
            exit;
            num++;
            cout << "Please type its meaning, if you have no idea, please type 'idk'" << endl;
            wcin.getline(VN, 100);
            if (VN != L"idk") {
                ENo2 << EN << endl;
                fprintf(fd, "%ws \n", VN);
            }
            else {
                ENo2 << EN << endl;
            }
            ENi.seekp(ios::beg);
            ENi2.seekp(ios::beg);
            ENo.seekp(ios::beg);
            ENo2.seekp(ios::beg);
        }
        case 2: {
            cout << "What word would you like to translate?" << endl;
            cin.getline(EN, 100);
            string EN2;
            wstring VN2;
            int check = 0;
            while (!ENi.eof()) {
                ENi >> EN2;
                out.imbue(loc); //đọc TV
                getline(out, VN2);
                if (EN2 == EN) {
                    check = 1;
                    break;
                }
            }
            if (check == 1)
                wcout << "According to this dictionary, the meaning of this word is: " << VN2 << endl;
            if (check == 0) {
                int mode;
                cout << "This word haven't been added to your dictionary yet" << endl;
                cout << "Add it now?" << endl;
                cout << "1. Yes" << endl << "2. No" << endl;
                cin >> mode;
                switch (mode) {
                case 1: {
                    ENo << EN;
                    cout << "Please type its meaning, if you have no idea, please type 'idk'" << endl;
                    wcin.getline(VN, 100);
                    if (VN != L"idk") {
                        ENo << EN << endl;
                        fprintf(fd, "%ws \n", VN);
                    }
                    else {
                        ENo2 << EN << endl;
                    }
                }
                case 2: {
                    break;
                }
                }
            }
            ENi.seekp(ios::beg);
            ENi2.seekp(ios::beg);
            ENo.seekp(ios::beg);
            ENo2.seekp(ios::beg);
        }
        case 3: {
            cout << "Preparing..." << endl << "Please wait..." << endl;
            string EN2;
            wstring VN2;
            int check = 0;
            int dem = 0;
            while (!ENi2.eof()) {
                ENi2 >> EN2;
                dem++;
            }
            if (dem == 0) {
                cout << "There's no words without meanings in your dictionary" << endl;
                break;
            }
            string** idk = new string * [dem];
            for (int i = 0; i < dem; i++) {
                idk[i] = new string;
            }
            if (dem != 0) {
                ENi2.seekp(ios::beg);
                dem = 0;
                while (!ENi2.eof()) {
                    ENi2 >> idk[dem][0];
                    dem++;
                }
            }
            cout << "Please add the meaning of these below words, if you still have no idea, please type 'idk'" << endl;
            for (int i = 0; i < dem; i++) {
                cout << idk[i][0];
                wcin.getline(VN, 100);
                if (VN != L"idk") {
                    fprintf(fd, "%ws", VN);
                    ENo << idk[i][0];
                    delete idk[i];
                }
            }
            fstream ENo3("EN2.txt", ios::out);
            for (int i = 0; i < dem; i++) {
                ENo3 << idk[i][0];
            }
            ENi.seekp(ios::beg);
            ENi2.seekp(ios::beg);
            ENo.seekp(ios::beg);
            ENo2.seekp(ios::beg);
        }
        case 4: {
            break;
        }
        default: {
            break;
        }
        }
    }
    return 0;
}

问题根源分析

Debug Assertion Failure通常由内存非法访问、文件操作冲突、流状态错误等引发,你的代码存在以下关键问题:

  • C/C++流混合操作冲突:同时用FILE*和wifstream打开VN.txt,两种IO库缓存机制不同,导致文件指针混乱触发断言。
  • 输入缓冲区残留问题:cin >> quit读取数字后,换行符留在缓冲区,后续cin.getline()会直接读取空字符串,引发流状态异常。
  • Switch分支无break:case 1、2等分支未加break,执行完当前分支后会继续执行后续逻辑,导致非法文件操作和内存访问。
  • 字符串比较错误:VN != L"idk"是比较指针地址而非字符串内容,应使用wcscmp(VN, L"idk") != 0。
  • 流定位错误:输入流使用seekp(输出流定位函数),应改为seekg。
  • 内存泄漏与越界:动态分配的二维数组未完全释放,且dem被重复赋值导致数组大小不匹配,引发越界访问。
  • 未处理文件打开失败:Num.txt不存在时num未初始化,引发后续逻辑错误。

修复后的代码示例

#include <iostream>
#include <fstream>
#include <string>
#include <io.h>
#include <fcntl.h>
#include <stdio.h>
#include <codecvt>
#include <locale>
#include <cstring>
#pragma warning (disable:4996)
using namespace std;

int main() {
    // 统一使用C++流操作,避免混合C流
    wofstream fd("VN.txt", ios::app);
    if (!fd.is_open()) {
        cerr << "Failed to open VN.txt" << endl;
        return 1;
    }

    // 设置控制台输入输出为UTF-8
    int ngu = _setmode(_fileno(stdin), _O_U8TEXT);
    int dumb = _setmode(_fileno(stdout), _O_U8TEXT);
    locale loc(locale(), new codecvt_utf8<wchar_t>);
    fd.imbue(loc);

    wifstream VN_in(L"VN.txt");
    ifstream ENi("EN.txt", ios::in);
    ofstream ENo("EN.txt", ios::app);
    ifstream ENi2("EN2.txt", ios::in);
    ofstream ENo2("EN2.txt", ios::app);
    ifstream so("Num.txt", ios::in);

    int num = 0;
    if (so.is_open()) {
        so >> num;
        so.close();
    }

    int quit = 0;
    char EN[100];
    wchar_t VN[100];
    while (quit != 5) {
        wcout << L"Pick a number:" << endl;
        wcout << L"1. Add a word" << endl;
        wcout << L"2. Translate a word using data from this program" << endl;
        wcout << L"3. Add the missing meaning for a word" << endl;
        wcout << L"4. Test your memory with random words from this dictionary" << endl;
        wcout << L"5. Exit" << endl;

        // 清除输入缓冲区残留的换行符
        cin.clear();
        cin.ignore(1000, '\n');
        cin >> quit;

        switch (quit) {
        case 1: {
            cout << "Please type the word you want to add:" << endl;
            cin.clear();
            cin.ignore(1000, '\n');
            cin.getline(EN, 100);

            num++;
            wcout << L"Please type its meaning, if you have no idea, please type 'idk'" << endl;
            wcin.getline(VN, 100);

            if (wcscmp(VN, L"idk") != 0) {
                ENo2 << EN << endl;
                fd << VN << L"\n";
            } else {
                ENo2 << EN << endl;
            }

            // 输入流用seekg定位
            ENi.seekg(ios::beg);
            ENi2.seekg(ios::beg);
            break;
        }
        case 2: {
            cout << "What word would you like to translate?" << endl;
            cin.clear();
            cin.ignore(1000, '\n');
            cin.getline(EN, 100);

            string EN2;
            wstring VN2;
            int check = 0;

            ENi.seekg(ios::beg);
            VN_in.seekg(ios::beg);
            VN_in.imbue(loc);

            while (ENi >> EN2 && getline(VN_in, VN2)) {
                if (EN2 == EN) {
                    check = 1;
                    break;
                }
            }

            if (check == 1) {
                wcout << L"According to this dictionary, the meaning of this word is: " << VN2 << endl;
            } else {
                int mode;
                cout << "This word haven't been added to your dictionary yet" << endl;
                cout << "Add it now?" << endl;
                cout << "1. Yes" << endl << "2. No" << endl;

                cin.clear();
                cin.ignore(1000, '\n');
                cin >> mode;

                switch (mode) {
                case 1: {
                    ENo << EN << endl;
                    wcout << L"Please type its meaning, if you have no idea, please type 'idk'" << endl;
                    wcin.getline(VN, 100);

                    if (wcscmp(VN, L"idk") != 0) {
                        fd << VN << L"\n";
                    } else {
                        ENo2 << EN << endl;
                    }
                    break;
                }
                case 2: {
                    break;
                }
                default:
                    break;
                }
            }
            ENi.seekg(ios::beg);
            ENi2.seekg(ios::beg);
            break;
        }
        case 3: {
            wcout << L"Preparing..." << endl << L"Please wait..." << endl;
            string EN2;
            int dem = 0;

            ENi2.seekg(ios::beg);
            while (ENi2 >> EN2) {
                dem++;
            }

            if (dem == 0) {
                wcout << L"There's no words without meanings in your dictionary" << endl;
                break;
            }

            // 改用一维数组存储单词,避免内存管理复杂
            string* idk = new string[dem];
            ENi2.seekg(ios::beg);
            for (int i = 0; i < dem; i++) {
                ENi2 >> idk[i];
            }

            wcout << L"Please add the meaning of these below words, if you still have no idea, please type 'idk'" << endl;
            ofstream ENo3("EN2.txt", ios::out);

            for (int i = 0; i < dem; i++) {
                wcout << idk[i].c_str() << L": ";
                wcin.getline(VN, 100);

                if (wcscmp(VN, L"idk") != 0) {
                    fd << VN << L"\n";
                    ENo << idk[i] << endl;
                } else {
                    ENo3 << idk[i] << endl;
                }
            }

            delete[] idk; // 释放动态分配的内存
            break;
        }
        case 4: {
            wcout << L"Function not implemented yet" << endl;
            break;
        }
        case 5: {
            // 退出时保存单词计数到Num.txt
            ofstream so_out("Num.txt", ios::out);
            so_out << num;
            so_out.close();
            break;
        }
        default: {
            wcout << L"Invalid option, please try again" << endl;
            break;
        }
        }
    }

    // 关闭所有文件流
    fd.close();
    VN_in.close();
    ENi.close();
    ENo.close();
    ENi2.close();
    ENo2.close();

    return 0;
}

关键修改说明

  1. 移除C风格FILE*操作,统一使用C++宽字符流处理UTF-8文本,避免IO冲突。
  2. 每次调用getline前用cin.ignore()清除输入缓冲区残留的换行符,解决空读问题。
  3. 为所有switch分支添加break,防止逻辑串流。
  4. 使用wcscmp比较宽字符串内容,替代指针地址比较。
  5. 输入流改用seekg定位,修正流定位错误。
  6. 简化动态内存分配为一维数组,正确释放内存,避免泄漏和越界。
  7. 添加文件打开失败判断,以及退出时保存单词计数的逻辑。
  8. 统一使用wcout输出宽字符,确保越南语显示正常。

内容的提问来源于stack exchange,提问作者Thọ Cáp Hữu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 23:07:01