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

实现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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:04:06