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

C语言读取txt文件unsigned int值出现异常偏移问题排查

故障核心原因

两个直接bug完全匹配你描述的故障现象:

  • 最致命的错误:你将char*类型的字符串返回值直接强转为unsigned int,这个操作不会把字符串里存储的数字文本转换成对应整数值,只会把字符串在内存中的首地址当作整数赋值给变量。同一次程序运行中,malloc分配的堆内存地址是连续线性的,所以所有读取结果的偏移量固定;开了地址随机化(ASLR)的系统上每次程序启动的堆基地址都不固定,所以不同次运行的偏移量完全随机。
  • fileFgets函数里的内存分配逻辑错误:malloc(strlen(tempStr) * sizeof(str))里sizeof(str)计算的是char指针的大小(32位系统是4字节、64位系统是8字节),不是char类型的1字节,且没有给字符串结尾的\0预留1字节空间,目前读字符串没出问题纯是内存布局的巧合,长文本场景会直接触发内存越界崩溃。
修复方案

你可以根据自己的代码习惯选下面任意一种方案:

方案1:修正通用逐行读取函数,配套正确的类型转换

先修复fileFgets的内存分配bug,增加错误处理:

#define MAX_STR_SIZE 1024 // 保持你原有宏定义即可
char* fileFgets(FILE* file) {
    char tempStr[MAX_STR_SIZE] = {0};
    // 处理文件尾、读失败的边界情况
    if (fgets(tempStr, MAX_STR_SIZE, file) == NULL) {
        return NULL;
    }
    // 同时兼容\n和Windows平台\r\n换行格式
    tempStr[strcspn(tempStr, "\r\n")] = 0;
    // 正确计算分配长度:内容长度+1预留结束符位置,char类型大小固定为1
    char* str = (char*)malloc(strlen(tempStr) + 1);
    if (str == NULL) return NULL;
    strcpy(str, tempStr);
    return str;
}

绝对不能直接把char指针强转为整数类型*,读取无符号整数时,需要把返回的数字字符串用标准库函数解析为对应数值:

char* numLine = fileFgets(file);
if (numLine == NULL) {
    // 自行补充读失败、到文件尾的处理逻辑
}
unsigned int tempDuration;
char* parseEnd = NULL;
// 用strtoul做无符号数值解析,比atoi支持错误校验
unsigned long parseRes = strtoul(numLine, &parseEnd, 10); // 最后一个参数10表示按十进制解析
// 跳过解析末尾的空白符
while (isspace(*parseEnd)) parseEnd++;
if (*parseEnd != '\0') {
    // 自行补充当前行内容不是合法无符号整数的异常处理
}
tempDuration = (unsigned int)parseRes;
free(numLine); // malloc申请的内存在用完后必须手动释放,避免内存泄漏

读取普通字符串时直接使用返回的char*即可,用完同样记得调用free释放。

方案2:拆分专用读取函数,降低误用概率

如果觉得统一读字符串再手动转换麻烦,可以分别实现字符串、无符号整数的专用读取函数,从接口层面避免指针强转的误用:

#include <ctype.h> // 用到isspace函数需要引入这个头文件

#define MAX_STR_SIZE 1024

// 专用逐行读字符串函数
char* readStringLine(FILE* file) {
    char tempStr[MAX_STR_SIZE] = {0};
    if (fgets(tempStr, MAX_STR_SIZE, file) == NULL) return NULL;
    tempStr[strcspn(tempStr, "\r\n")] = 0;
    char* res = (char*)malloc(strlen(tempStr) + 1);
    if (res == NULL) return NULL;
    strcpy(res, tempStr);
    return res;
}

// 专用逐行读无符号整数函数,返回值0表示读取成功,非0为错误码
int readUintLine(FILE* file, unsigned int* outVal) {
    char tempStr[MAX_STR_SIZE] = {0};
    if (fgets(tempStr, MAX_STR_SIZE, file) == NULL) return -1;
    char* parseEnd = NULL;
    unsigned long parseRes = strtoul(tempStr, &parseEnd, 10);
    while (isspace(*parseEnd)) parseEnd++;
    if (*parseEnd != '\0') return -2;
    *outVal = (unsigned int)parseRes;
    return 0;
}

调用时直接对应数据类型选择函数即可:

// 读字符串
char* content = readStringLine(file);
// 用完后free(content)

// 读无符号整数
unsigned int tempDuration;
int readRet = readUintLine(file, &tempDuration);
if (readRet != 0) {
    // 自行补充读失败、内容非法的处理逻辑
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 22:06:27