You need to enable JavaScript to run this app. 使用lseek获取文件大小时返回值小于实际大小的异常问题咨询
优惠活动
大模型
产品
解决方案
定价
更多

使用lseek获取文件大小时返回值小于实际大小的异常问题咨询

问题根因排查及修复方案

核心问题1:返回值类型不匹配

lseek的函数原型为off_t lseek(int fd, off_t offset, int whence);,返回值类型是操作系统定义的off_t(文件偏移量专用类型),你的代码中使用int类型接收返回值,会直接导致截断错误:

  • 32位环境、或者未开启大文件编译选项时,off_t默认是32位有符号整型,最大仅支持表示2GB大小的文件,只要文件大小超过2^31-1,返回值就会溢出,得到错误结果
  • 64位环境下off_t是64位整型,用32位的int接收会直接截断高位,结果必然不正确

核心问题2:缺少错误判断逻辑

你的代码完全没有校验lseek的返回值,如果打开的是不支持随机寻址的特殊文件(管道、FIFO、套接字、procfs虚拟文件等),lseek会返回-1表示调用失败,你直接将-1作为文件大小输出,自然无法得到正确结果。

其他可能触发该现象的场景

如果你是通过其他进程向目标文件追加数据,追加完成后没有调用close()或者fsync()/fdatasync(),修改的文件元数据(大小)还停留在操作系统页缓存中没有落盘,此时你的程序读取到的还是磁盘上存储的旧元数据,就会返回旧文件大小。

另外原代码中两次定位到文件开头的操作属于冗余逻辑,不影响运行结果但没有实际作用,可以直接删除。


修复后的代码示例

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc,char* argv[]){
    // 改用off_t类型存储文件大小
    off_t out_file_size=0;
    int fd_prognameout;

    if(argc < 2){
        printf("请传入文件路径参数\n");
        return 1;
    }

    fd_prognameout=open(argv[1],O_RDWR | O_CREAT,00700);
    if(fd_prognameout == -1){
        perror("打开文件失败");
        return 1;
    }

    // 直接用SEEK_END获取大小,不需要多余的seek操作
    out_file_size = lseek(fd_prognameout,0,SEEK_END);
    if(out_file_size == (off_t)-1){
        perror("获取文件大小失败");
        close(fd_prognameout);
        return 1;
    }

    // 64位off_t用%lld输出,强制转型避免格式警告
    printf("The size of out file is: %lld\n",(long long)out_file_size);
    
    close(fd_prognameout);
    return 0;
}

编译时需要添加大文件支持参数,避免32位环境下的大小截断:

gcc -D_FILE_OFFSET_BITS=64 your_code.c -o get_file_size

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.18 03:06:03