C语言同进程可读写二进制文件,单独读取时触发段错误求助
问题拆解与解决方案
这个问题我太熟悉了,你踩了二进制文件读写里的两个经典坑——结构体内存分配错误和指针序列化的误区,咱们一步步理清楚:
1. 首先是致命的内存分配错误
看你代码里的这行:
new = (details *)malloc(sizeof(new));
这里new是details*类型的指针,sizeof(new)拿到的是指针本身的大小(64位系统里是8字节,32位是4字节),而不是details结构体的完整大小!这就导致你只分配了一小块内存,后续给new->num和new->name赋值时,大概率会触发内存越界,为后续的段错误埋下隐患。
正确的写法应该是分配结构体的大小:
new = (details *)malloc(sizeof(details));
2. 核心问题:字符串指针的二进制写入无效
你结构体里的char *name是个指针,当你用fwrite直接写入整个结构体时,写入的只是指针存储的内存地址,而不是指针指向的字符串内容。
- 同一程序流程里读取时,这个地址还在当前进程的地址空间里,所以能正常访问到字符串;
- 但单独启动程序读取时,这个地址已经不属于当前进程的有效内存(甚至可能是内核空间),直接访问就会触发段错误。
两种解决思路
思路一:用固定大小字符数组代替指针
如果你的字符串长度是可预估的,直接把结构体改成固定数组的形式,这样字符串内容会直接存在结构体里,读写都不用额外处理:
typedef struct Details { int num; char name[256]; // 根据需求调整大小,确保能容纳最长的字符串+终止符 } details;
这种方式最简单,适合大多数场景。
思路二:手动序列化字符串(适合动态长度字符串)
如果必须用指针,那就要分开写入结构体的非指针部分、字符串长度和字符串内容,读取时反向操作:
修正后的写入函数
int writeData(char *filename, details *data) { FILE *fp = fopen(filename, "wb"); // 先写入num fwrite(&data->num, sizeof(int), 1, fp); // 写入字符串长度(包含终止符,方便读取时分配内存) size_t name_len = strlen(data->name) + 1; fwrite(&name_len, sizeof(size_t), 1, fp); // 写入字符串内容 fwrite(data->name, sizeof(char), name_len, fp); fclose(fp); return 0; }
修正后的读取函数
int readData(char *filename) { // 注意你原来的参数写错了,是char不是chhar FILE *fp = fopen(filename, "rb"); details data; // 读取num fread(&data.num, sizeof(int), 1, fp); // 读取字符串长度 size_t name_len; fread(&name_len, sizeof(size_t), 1, fp); // 分配内存存储字符串 data.name = malloc(name_len); // 读取字符串内容 fread(data.name, sizeof(char), name_len, fp); // 这里可以使用读取到的数据 printf("读取到的num: %d,name: %s\n", data.num, data.name); // 记得释放内存,避免泄漏 free(data.name); fclose(fp); return 0; }
最后还要提个小细节:你代码里的readData参数写成了chhar *,是拼写错误,要改成char *,否则编译都通不过。
内容的提问来源于stack exchange,提问作者MkPtr
相关产品推荐
相关产品推荐

