如何修复char数组引发的Run-Time Check Failure #2缓冲区溢出问题?
问题分析与解决方案
核心问题定位
缓冲区溢出根源
- 定义
char pword[Size]时,Size=10,但C风格字符串需要末尾的'\0'作为结束标记,这个数组最多只能容纳9个有效字符。输入10个字符的密码时会直接溢出栈空间,触发栈损坏错误。 - 代码中错误地将空字符写成
'\\0'(多了一个反斜杠),导致循环无法正确识别字符串结束位置,count持续递增,越界访问数组进一步破坏栈结构。 bool state = NULL是错误用法,NULL是指针类型的空值,布尔类型应初始化为false。
- 定义
逻辑漏洞
- 未验证密码总长度是否为10,
psize变量完全未使用。 - 密码规则是恰好4个小写字母+6个数字,原代码判断
totall >4 || totaln>6逻辑错误,应该检查totall !=4 || totaln !=6,同时确保总长度是10。
- 未验证密码总长度是否为10,
错误的动态分配尝试
- 你写的
pword[Size]= (char*)malloc(sizeof(char))={};完全不符合C/C++语法。动态分配C风格数组需要先声明指针,再分配足够的内存空间。
- 你写的
修复后的完整代码
// 验证输入密码是否有效:10字符,4个小写字母+6个数字,顺序不限 #include<iostream> #include<cctype> #include<cstring> using namespace std; int main() { const int PWD_LENGTH = 10; // 数组大小设为11,预留'\0'的位置 char pword[PWD_LENGTH + 1]; int count = 0; int letter_count = 0; int digit_count = 0; bool is_valid = false; while (!is_valid) { cout << "请输入10位密码(4个小写字母+6个数字):" << endl; // 使用cin.getline避免溢出,限制读取10个字符+1个'\0' cin.getline(pword, PWD_LENGTH + 1); int pwd_size = strlen(pword); letter_count = 0; digit_count = 0; is_valid = true; // 先检查长度是否符合要求 if (pwd_size != PWD_LENGTH) { cout << "错误!密码必须是10个字符。" << endl; is_valid = false; continue; } // 遍历每个字符验证类型 for (count = 0; count < PWD_LENGTH; ++count) { if (islower(pword[count])) { letter_count++; } else if (isdigit(pword[count])) { digit_count++; } else { // 既不是小写字母也不是数字 cout << "错误!所有字符必须是小写字母或数字。" << endl; is_valid = false; break; } } // 验证字母和数字的数量是否符合规则 if (is_valid && (letter_count != 4 || digit_count != 6)) { cout << "错误!密码必须包含恰好4个小写字母和6个数字。" << endl; is_valid = false; } } cout << "你输入的密码是:" << pword << endl; cout << "密码中小写字母的数量是:" << letter_count << endl; cout << "密码中数字的数量是:" << digit_count << endl; return 0; }
正确的动态内存分配方式
1. C风格malloc/free
如果要用C的动态分配,需要给指针分配足够的内存(包含'\0'的空间):
const int PWD_LENGTH = 10; // 分配11个字符的空间:10个密码字符 + 1个'\0' char* pword = (char*)malloc((PWD_LENGTH + 1) * sizeof(char)); // 使用前检查是否分配成功 if (pword == nullptr) { cerr << "内存分配失败" << endl; return 1; } // 使用完成后必须释放内存 free(pword); pword = nullptr; // 避免野指针
2. C++风格new/delete
更符合C++规范的方式:
const int PWD_LENGTH = 10; char* pword = new char[PWD_LENGTH + 1]; // 可选:用nothrow版本避免抛出异常 char* pword = new(nothrow) char[PWD_LENGTH + 1]; if (pword == nullptr) { cerr << "内存分配失败" << endl; return 1; } // 使用后释放 delete[] pword; pword = nullptr;
3. 更推荐的C++方式:std::string
在C++中,完全没必要手动管理C风格字符数组,直接用std::string可以自动处理内存,避免缓冲区溢出:
#include<string> // ... string pword; while (!is_valid) { cout << "请输入10位密码:" << endl; cin >> pword; // 直接用pword.size()获取长度,无需处理'\0' if (pword.size() != 10) { cout << "错误!密码必须是10个字符。" << endl; continue; } // 遍历验证字符更方便 for (char c : pword) { if (islower(c)) { letter_count++; } else if (isdigit(c)) { digit_count++; } else { cout << "错误!所有字符必须是小写字母或数字。" << endl; is_valid = false; break; } } // 验证数量规则... }
内容的提问来源于stack exchange,提问作者Henry Lj
相关产品推荐
相关产品推荐

