实现Book Cipher时触发内存访问错误(Access Violation)求助
解决Book Cipher中的内存访问错误问题
首先,你的代码出现**内存访问错误(Access Violation)**的核心原因非常明确:你在main函数里声明了int *crypted;,但这个指针只是一个未初始化的野指针——它没有指向任何合法的内存空间,当你在encrypting函数里尝试给result[i]赋值时,本质是在往随机的内存地址写数据,这直接触发了系统的内存保护机制。
具体修正步骤
1. 给指针分配合法内存
在main函数中,拿到字符串长度slength之后,需要用new为crypted分配对应大小的内存:
slength = s_true.length(); crypted = new int[slength]; // 新增:分配能存储slength个int的内存
同时,为了避免内存泄漏,程序结束前记得释放内存:
delete[] crypted; // 在return 0之前添加
2. 修正加密函数的循环条件
你的while(s_true[i])循环存在隐患:std::string并不保证以\0结尾(虽然多数实现会包含,但不符合标准规范),正确的循环逻辑应该基于字符串的实际长度:
for(int i = 0; i < s_true.size(); i++) { // 原来的加密逻辑 }
3. 补充输入合法性检查
你原来的代码只检查了s_true的字符是否为大写,但没检查s_false,这可能导致column计算出错,需要补上对应检查。
4. 添加随机种子
生成随机密码表时,记得调用srand(time(0));,否则每次运行程序生成的密码表完全一致,失去了随机性。
完整修正后的代码
所有修改点都已标注:
#include <iostream> #include <cstdlib> #include <string> #include <algorithm> #include <vector> #include <ctime> using namespace std; void generate( int tab[26][26] ) { int h; vector<int> table; for(int i = 0; i<676; i++) { table.push_back(i+1); } int g = 0; srand(time(0)); // 新增:添加随机种子,保证每次生成不同密码表 random_shuffle(table.begin(), table.end()); for(int x = 0; x < 26; x++) { for(int y = 0; y < 26; y++) { tab[x][y] = table[g]; g++; } } } void print_cipher_table(int tab[26][26]) { char sign = 'A'; cout << " "; for (int n = 0; n<26; n++) { cout << sign++ << " "; } cout << "\n"; sign = 'A'; for(int x = 0; x<26; x++) { cout << sign++ << " "; for(int y = 0; y<26; y++) { if(tab[x][y] < 10) cout << "00" << tab[x][y] << " "; else if(tab[x][y] < 100) cout << "0" << tab[x][y] << " "; else cout << tab[x][y] << " "; } cout << "\n"; } } void encrypting(int tab[26][26], string s_true, string s_false, int *result) { int row, column; // 修改:用for循环替代while,基于字符串长度循环更安全 for(int i = 0; i < s_true.size(); i++) { // 新增:同时检查s_true和s_false的字符是否为大写 if(s_true[i] > 64 && s_true[i] < 91 && s_false[i] > 64 && s_false[i] < 91) { row = s_true[i] -'A'; column = s_false[i] - 'A'; } else { cout << "NIE PODAŁEŚ WIELKICH LITER!" << endl; exit(0); } cout << "\t" << tab[row][column]; result[i] = tab[row][column]; } } int main() { int tab[26][26], slength, *crypted = nullptr; // 初始化指针为nullptr更安全 string s_true, s_false; string letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; cout << "Prosze podac tekst prawdziwy: "; cin >> s_true; cout << "Prosze podac tekst falszywy: "; cin >> s_false; if(s_true.length() != s_false.length()) { cout << "Chujowa dlugosc tekstu. Wypierdalaj"; exit(1); } slength = s_true.length(); crypted = new int[slength]; // 新增:分配内存 generate( tab ); print_cipher_table( tab ); cout << "\n\n\n"; encrypting(tab, s_true, s_false, crypted); // 新增:打印所有加密结果,而非仅第一个元素 cout << "\n\n加密结果:"; for(int i=0; i<slength; i++){ cout << crypted[i] << " "; } delete[] crypted; // 新增:释放内存,避免泄漏 return 0; }
额外优化建议
- 推荐用
std::vector<int>替代手动分配的动态数组,无需手动管理内存,安全性更高:把int *crypted换成vector<int> crypted(slength);,encrypting函数参数改为vector<int>& result即可。 - 可以考虑把错误提示改成更友好的语言,同时避免直接调用
exit(0),改用返回错误码的方式让程序更优雅地退出。
内容的提问来源于stack exchange,提问作者Szymon 呕ak
相关产品推荐
相关产品推荐

