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

如何修复C语言结构体文件读写时的‘内存无法写入’错误?

C语言结构体文件读写错误排查与解决方案

问题说明

参考YouTube教程实现结构体读写文件功能,仅修改变量名后,用编译指令gcc -o _main _main.c编译运行时,弹出错误:

0x00000000765AF391处的指令引用了0x000000000000000F处的内存,该内存无法写入。
怀疑是内存泄漏导致,需要排查代码问题并学习C语言FILE操作知识。

错误原因逐条分析

  1. 结构体成员定义与初始化不匹配
    Worker结构体中workerCode被定义为int workerCode[5](整数数组),但初始化时却用.workerCode = 12345直接赋值单个整数。数组不能直接用单个值初始化,这会导致内存越界;后续fprintf用%d输出数组名时,实际是输出数组的内存地址而非工号值,fscanf读入时也会把值写到错误的内存位置。

  2. fscanf参数严重错误
    格式串WORKER_FORMAT_IN为(%[^,], %[^,], %d)\n,对应3个参数,但代码中传入了4个参数:worker2.workerFirstName, 15, &worker2.workerLasttName, &worker2.workerCode。其中15被fscanf当成第二个字符串的内存地址(15的十六进制是0xF,正好对应错误提示里的非法地址),往这个只读低地址写入数据直接触发内存访问错误。

  3. 结构体成员拼写错误
    Worker结构体中workerLasttName多写了一个t,虽然当前未直接引发错误,但属于潜在bug,后续维护时容易出错。

  4. 未关闭文件
    fopen打开文件后未调用fclose,虽然程序结束时系统会回收资源,但这是不良编程习惯,可能导致缓冲区数据未及时写入磁盘。

修复后的完整代码

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

typedef struct Client {
    char userFirstName[15];
    char userLastName[15];
    char userPassword[20];
    float userBankMoney;
    float userHandMoney;
} Client;

// 修正格式串:给字符串读取添加长度限制,避免缓冲区溢出
const char* WORKER_FORMAT_IN = "(%14[^,], %14[^,], %d)\n";
const char* WORKER_FORMAT_OUT = "(%s, %s, %d)\n";

typedef struct Worker {
    char workerFirstName[15];
    char workerLastName[15];  // 修正拼写错误
    int workerCode;           // 改为单个整数,符合工号的实际需求
} Worker;

//>>>FUNCTIONS PROTOTYPES<<<//
void printOptions();
void loginAsWorker();
void createAccount();
void payment();
void withdrawal();
void moneyTransfer();
void balanceReview(double balance);

int main() {
    Worker worker1 = {
        .workerFirstName = "Matija",
        .workerLastName = "Davidovic",
        .workerCode = 12345
    };
    Worker worker2;
    
    FILE* worker_file = fopen("worker.dat", "w+");
    if(worker_file == NULL) {
        perror("Failed to open file");  // 添加错误提示,便于排查
        return 1;
    }

    // 格式化写入结构体数据
    fprintf(worker_file, WORKER_FORMAT_OUT, 
            worker1.workerFirstName, worker1.workerLastName, worker1.workerCode);
    
    // 将文件指针移回开头,准备读取
    fseek(worker_file, 0, SEEK_SET);
    
    // 格式化读取数据,参数与格式串严格匹配
    fscanf(worker_file, WORKER_FORMAT_IN, 
           worker2.workerFirstName, worker2.workerLastName, &worker2.workerCode);
    
    // 验证读取结果(可选,用于调试)
    printf("Read worker data: %s, %s, %d\n", 
           worker2.workerFirstName, worker2.workerLastName, worker2.workerCode);
    
    // 关闭文件,释放资源
    fclose(worker_file);
    return 0;
}

C语言FILE操作关键知识点

  • 格式化读写参数匹配:fprintf/fscanf的格式串必须与后续参数的类型、数量、顺序完全一致,否则会触发未定义行为(比如内存访问错误)。
  • 字符串读取安全:使用%N[^,]格式限制读取长度(N为数组长度-1,留一位给字符串结束符\0),避免缓冲区溢出导致的内存问题。
  • 文件打开模式:w+模式会清空原有文件内容,若要保留原有内容并读写,应使用r+模式;写入后必须通过fseek/rewind将文件指针移回开头才能读取刚写入的数据。
  • 文件资源管理:打开的文件必须用fclose关闭,确保缓冲区数据写入磁盘,避免资源泄漏。
  • 结构体成员操作:数组类型的成员不能直接用单个值初始化或赋值,若只需存储单个值,应改为普通变量类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 17:29:58