如何修复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; }
关键修改说明
- 移除C风格
FILE*操作,统一使用C++宽字符流处理UTF-8文本,避免IO冲突。 - 每次调用
getline前用cin.ignore()清除输入缓冲区残留的换行符,解决空读问题。 - 为所有switch分支添加
break,防止逻辑串流。 - 使用
wcscmp比较宽字符串内容,替代指针地址比较。 - 输入流改用
seekg定位,修正流定位错误。 - 简化动态内存分配为一维数组,正确释放内存,避免泄漏和越界。
- 添加文件打开失败判断,以及退出时保存单词计数的逻辑。
- 统一使用
wcout输出宽字符,确保越南语显示正常。
内容的提问来源于stack exchange,提问作者Thọ Cáp Hữu
相关产品推荐
相关产品推荐

