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

C++调用oku()函数后出现Access Reading Error问题求助

解决你的C++二进制文件读取后内存访问错误问题

嘿,我一眼就看出问题出在哪了——你直接对包含std::string的结构体做二进制读写,这绝对是C++新手常踩的坑,也是导致你程序结束时触发Access Reading Error的根本原因。

为什么会崩溃?

std::string不是简单的字符数组,它内部是个带指针的容器:实际的字符串内容存在堆内存里,string对象本身只存了指向这块内存的指针、字符串长度这些元数据。当你用file2.read((char *)&kisi[i], sizeof(kisi[i]))直接把二进制数据读进结构体时:

  • 你读进来的是之前写入的旧指针地址,不是实际的字符串内容
  • 程序结束时,kisi数组里的所有string对象会自动调用析构函数,尝试释放这些旧指针指向的内存——但这些内存要么早就被释放了,要么根本不属于当前进程,自然就触发了内存访问错误(就是你看到的_Pnext相关报错)

另外,你的oku()函数里还有个小bug:循环内部又定义了int i = 0;,这会让循环永远只处理kisi[0],不过这不是崩溃的直接原因,但也得修。

怎么修复?

要正确读写带string的结构体,不能直接读写整个结构体,必须逐个成员处理,尤其是string类型的成员,得单独读写长度和内容:

1. 修复你的oku()函数

void oku() {
    cout << "okuma islemi yapiliyor";
    ifstream file2("kisi.txt", ios::in | ios::binary);
    // 一定要检查文件是否打开成功,不然白忙活
    if (!file2.is_open()) {
        cerr << "Dosya acilamadi!" << endl;
        return;
    }

    for (int i = 0; i < 20; i++) {
        cout << "suanda cursor " << file2.tellg() << endl;
        // 先读写基本数据类型的成员
        file2.read((char *)&kisi[i].id, sizeof(kisi[i].id));
        file2.read((char *)&kisi[i].cinsiyet, sizeof(kisi[i].cinsiyet));
        file2.read((char *)&kisi[i].depozito, sizeof(kisi[i].depozito));
        file2.read((char *)&kisi[i].oda_no, sizeof(kisi[i].oda_no));
        
        // 读写数组类型的成员
        file2.read((char *)kisi[i].odenmis_k, sizeof(kisi[i].odenmis_k));
        file2.read((char *)kisi[i].endeks, sizeof(kisi[i].endeks));
        file2.read((char *)kisi[i].fatura, sizeof(kisi[i].fatura));

        // 重点处理std::string成员:先读长度,再读内容
        size_t str_len;
        // 处理TC字段
        file2.read((char *)&str_len, sizeof(str_len));
        kisi[i].TC.resize(str_len);
        file2.read(&kisi[i].TC[0], str_len);
        // 处理Ad字段
        file2.read((char *)&str_len, sizeof(str_len));
        kisi[i].Ad.resize(str_len);
        file2.read(&kisi[i].Ad[0], str_len);
        // 剩下的string字段(Soyad、dogumgunu、tel等)都按这个逻辑处理
        file2.read((char *)&str_len, sizeof(str_len));
        kisi[i].Soyad.resize(str_len);
        file2.read(&kisi[i].Soyad[0], str_len);

        file2.read((char *)&str_len, sizeof(str_len));
        kisi[i].dogumgunu.resize(str_len);
        file2.read(&kisi[i].dogumgunu[0], str_len);

        file2.read((char *)&str_len, sizeof(str_len));
        kisi[i].tel.resize(str_len);
        file2.read(&kisi[i].tel[0], str_len);

        file2.read((char *)&str_len, sizeof(str_len));
        kisi[i].eposta.resize(str_len);
        file2.read(&kisi[i].eposta[0], str_len);

        file2.read((char *)&str_len, sizeof(str_len));
        kisi[i].girist.resize(str_len);
        file2.read(&kisi[i].girist[0], str_len);

        file2.read((char *)&str_len, sizeof(str_len));
        kisi[i].cıkıst.resize(str_len);
        file2.read(&kisi[i].cıkıst[0], str_len);
    }

    file2.close();
    cout << "Islem tamamlandi";
    getchar();
}

2. 对应的写入函数也要同步修改

如果你之前是用write((char *)&kisi[i], sizeof(kisi[i]))写入文件的,那必须改成和读取对应的方式,逐个成员写入,比如:

void yaz() {
    ofstream file("kisi.txt", ios::out | ios::binary);
    if (!file.is_open()) {
        cerr << "Dosya acilamadi!" << endl;
        return;
    }

    for (int i = 0; i < 20; i++) {
        // 写入基本类型成员
        file.write((char *)&kisi[i].id, sizeof(kisi[i].id));
        file.write((char *)&kisi[i].cinsiyet, sizeof(kisi[i].cinsiyet));
        file.write((char *)&kisi[i].depozito, sizeof(kisi[i].depozito));
        file.write((char *)&kisi[i].oda_no, sizeof(kisi[i].oda_no));
        
        // 写入数组
        file.write((char *)kisi[i].odenmis_k, sizeof(kisi[i].odenmis_k));
        file.write((char *)kisi[i].endeks, sizeof(kisi[i].endeks));
        file.write((char *)kisi[i].fatura, sizeof(kisi[i].fatura));

        // 写入string成员:先写长度,再写内容
        size_t str_len = kisi[i].TC.size();
        file.write((char *)&str_len, sizeof(str_len));
        file.write(kisi[i].TC.c_str(), str_len);

        str_len = kisi[i].Ad.size();
        file.write((char *)&str_len, sizeof(str_len));
        file.write(kisi[i].Ad.c_str(), str_len);

        // 剩下的string字段也按这个逻辑写进去
    }

    file.close();
}

3. 额外要注意的点

  • 每次操作文件都要检查是否打开成功,避免后续操作触发未定义行为
  • 把oku()循环里的int i = 0;删掉,不然循环变量被覆盖,逻辑全错
  • 如果以后修改了结构体的成员,读写函数也要同步更新,不然会出现数据错位的问题

内容的提问来源于stack exchange,提问作者Hakan Bakacak

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:25:26