V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
jim9606
V2EX  ›  C++

似乎在 C 的领域,让一个新程序“为未来准备好”是一件很麻烦的事

  •  1
     
  •   jim9606 · 1 天前 · 1962 次点击

    最近在修改一个 C 的开源小项目。因为是想在 Win 下用的,但项目是用 autoconf 构建的,所以准备了 MSYS2 UCRT64 环境来开发。然后就踩了处理不了大于 2G 文件的坑(用了 fstat)。虽然说就是一个 _FILE_OFFSET_BITS 宏的事,但毕竟是个跨平台项目,所以就查了下主流系统下这个问题的支持情况,感觉好多槽点。

    1. MSYS MinGW-w64 默认提供 32 位 off_t ,哪怕你在编译 64 位程序,想用需要上面的宏,但这并不是 POSIX 标准化的东西
    2. autoconf 有一个 AC_SYS_LARGEFILE 可以自动判断是否需要定义宏,但 autoscan 没提示需要这个
    3. 如果是 32 位 target ,似乎默认提供 32 位 off_t 是天经地义的
    4. 不想跟环境打哑谜的可以用明确 64 位的方法,例如 fseeko64 fstat64 ,但这玩意并不普遍可用,还是要构建系统检测。 例如老版本 android 就不支持。bionic 的文档说一大堆考量,结果就是想解决你得用较新的 ndk ,放弃支持旧版 android ,或者就放弃支持 32 位 abi 。(所以实际上哪怕是 arm64-v8a 的 android 系统依然有机会在处理大文件时出问题)
    5. 哪怕你不关心文件大小也可能被影响,例如查个文件创建日期就要用到 fstat ,尽管觉得做的事跟大小无关但就是有影响
    6. 如果在 abi 边界用了这些带 off_t 的变量/struct ,显然会出现 abi 不兼容问题,你也不知道一个第三方库可能用哪种配置

    个人觉得 2GB 以上大文件并不是什么很罕见的用例,为什么开发环境就不能默认支持这些情况呢,难道还影响兼容性?

    标题里的“为未来准备好”是指,只使用跨平台的 C/C++,加上 2000 年后的 POSIX:

    1. 已解决 2038 问题
    2. 除非明确要求,否则文本存储和 IO 都是 UTF-8 且不使用 wchar_t
    3. 无论环境如何都能正确在 ui 或控制台输出非 ASCII 字符
    4. 不拒绝使用 IPv6
    5. 支持长路径
    6. 保持对近十年出厂的系统和硬件的支持

    似乎要在无第三方依赖的情况下做到这个是很困难的事?

    17 条回复    2026-04-09 17:14:48 +08:00
    Thymolblue
        1
    Thymolblue  
       19 小时 28 分钟前
    - 即使是 2026 年了,微软也没解决中文路径编码问题。我在程序里的字符串统一使用的是 UTF-8 编码,POSIX 下没有任何问题,但是在 Windows 下路径直接就识别不了。
    - 另外跨平台项目更推荐使用 CMake 提供构建支持。autoconf 依赖 bash 环境,不是所有设备都能够很容易安装的。
    - 现在很多开源的都库不支持编译成 32 位,32 位的系统也不常见了,不如直接只支持 64 位设备。
    pursuer
        2
    pursuer  
       19 小时 11 分钟前
    因为 C/C++跨平台本就不怎么样,autoconf 更是重量级,要跨平台就 libuv+CMake 。
    确实 2GB 以上大文件不算罕见,但就像你说的,这是 ABI 不兼容,对于 c/c++,兼容性更重要。虽然 Glibc 自己都做不好 ABI 兼容。
    xtreme1
        3
    xtreme1  
       18 小时 53 分钟前
    因为在 WINAPI / libc 层面是玩不了黑魔法的, 分分钟内存越界
    capric
        4
    capric  
       18 小时 42 分钟前
    你让 ai 把 autoconf 转换为 meson ,然后用 zig cc 当交叉编译器就很舒服
    penisulaS
        5
    penisulaS  
       18 小时 41 分钟前
    见过一个项目直接用 rust 写壳包 c 核,就是因为 posix 兼容太烦人
    changnet
        6
    changnet  
       18 小时 13 分钟前
    1. posix 是一套操作系统接口标准,而 C 是一门语言。写 C 不能按 posix 去写。就好比打包出来一个 apk ,老是有人问在 win 上为什么安装不了 apk 一样。
    1. posix 在 linux 下还行,但在 win 下就是不行。这个是微软的问题,它早年就是独立于 posix 的。后来 posix 用得广了才勉为其难加了兼容接口,但一直不怎么维护,和 posix 的兼容性也不太好。
    2. C/C++都是专注于语言而不是应用,它们所给的标准都是基于语言层面的。各个平台自己咋实现它不管。所以它的标准库接口很少,stl 也很少。很多功能必须用系统 api
    3. minGW 和 CyWin 这东西本来就冷门,维护也是跟不上的。我试过把 linux 上的程序迁移到 win ,想着用 CyWin 可以少改些。但实际勉强能跑起来但很难维护,第三方库大多没有官方支持,所以直接切换到 MSCV 了。
    4. C/C++现代一些的应该是用 CMake 的项目,autoconf 应该是 linux 下的项目了。

    C/C++因为历史的原因,它就是没法做到像其他语言那样跨平台 api 统一的。如果是新项目,用 cmake + 新标准(比如 C++ 17 以上)可以解决 90%的问题,比如你说的用 C++的 std::filesystem 应该是可以的。剩下的 10%用各自原生的平台接口维护(比如网络接口)。

    但你是旧项目,要么全改,要么写各种兼容
    Mithril
        7
    Mithril  
       18 小时 11 分钟前   ❤️ 1
    所以“新程序”已经尽量不用 C/C++来写了,特别是如果你的程序想要跨平台的话,项目做大了就会发现到处都是坑。

    更别说你做个开源项目了,大半精力都要花在维护这些乱七八糟的编译环境上。
    Mithril
        8
    Mithril  
       18 小时 4 分钟前
    另外基于我之前做的调查结果,最省心最简单的 C++跨平台,就是你只针对 Windows 开发,然后各种*nix 全用 Wine/Proton 去跑。

    Wine 上面的 API 兼容需要测试,你用到一些奇怪的 API 很可能在 Wine 上跑不通。不过但凡能跑通,绝对比你去每个平台维护一套编译,测试,要容易太多了。测试通过以后把 Windows 的二进制扔进去直接跑。

    有人说 Wine 是各种 Linux 上最稳定的 ABI 不是没有道理的。各种发行版你要都支持,光是 glibc/Musl 都能搞你一下。

    缺点就是这项目维护最好的只有游戏能用得到的那些 API ,如果你的程序还要调用别的 API ,比如硬件相关的,那就没办法了。
    capric
        9
    capric  
       17 小时 42 分钟前
    @penisulaS 我就是这样的,这样上层 rust 用 cargo-zigbuild 交叉编译,底层 c 也一起交叉编译
    capric
        10
    capric  
       17 小时 41 分钟前
    @capric 还把 rust 数据结构暴露给 c 用
    Ketteiron
        11
    Ketteiron  
       17 小时 14 分钟前
    Rust 会流行,有很大原因就是 C/C++ 这些狗屁倒灶的事情无法解决。
    根本原因还是 ABI ,C/C++ 选择绝对的向后兼容,代价就是历史遗留问题几乎无法处理; Rust 非常激进走了另一条路,不提供任何稳定 ABI ,因此清理历史包袱的代价非常轻。但是,哈哈,Rust 有稳定的 C ABI 。
    要我说,还是 C++ 太贪婪了,既想要一切抽象和范式,又想要保证向后兼容,还得为 n 个平台擦屁股,根本是做梦。
    目前最务实的做法还是 Rust + C ,两个语言都有各自的破事,不如合起来只用最好的部分。
    xuanbg
        12
    xuanbg  
       16 小时 51 分钟前
    直接让 AI 翻译成 rust 好了
    WorseIsBetter
        13
    WorseIsBetter  
       16 小时 37 分钟前
    我的个人项目(参考我发的第一个主题帖)也有处理 32-bit/64-bit 的 off_t/time_t 。我觉得这块其实是很 trivial 的,没你说的那么复杂。

    原则只有一条:管好自己的项目就行。

    你的代码里需要意识到这些类型有 32-bit 和 64-bit 两种可能,并且分别对其做支持(或者不对某些情况做支持并让构建过程失败),就足够了。至于和其他程序的 ABI 兼容,是由发行版的包维护者或者用户自己(如果他们选择自行构建)来保证的。

    除此之外,你唯一能做的,大概只有把构建脚本写得更灵活、优雅,再配上清晰明确的构建文档,让包维护者和用户少走或不走弯路。

    另外:不建议依靠 autoscan ,那玩意只起到一个基本的示例作用,对实际项目的帮助不大。还是得想清楚自己具体需要在 autoconf.ac 中检查什么、配置什么,然后根据需求来写
    xiliuya
        14
    xiliuya  
       13 小时 15 分钟前
    不要用 windows 就可以完美解决这个问题,不是 c/c++的问题,而是 win 的锅。
    beautyplus
        15
    beautyplus  
       12 小时 43 分钟前
    本质还是编码对不上,跟 windows 系统 **交互** 是要尽量用 wchar 的,尤其是带路径参数的函数比如 wfopen ,CreateFileW ,因为你不确定目标机器有没有开启 utf-8 (区域设置中的使用 utf-8 还标记着 beta 默认不勾选)
    cnbatch
        16
    cnbatch  
       11 小时 18 分钟前
    这是 C 的事情,发到 C++板块不怎么妥当吧

    前半部分

    1 ,这是 MSYS MinGW 的锅,它们没处理好 64 位的适配。Windows 提供了 fseeko64 的替代品 _fseeki64(),中间转换层本该做好映射支持的。
    2~6 ,这就是系统 API / SDK 的锅,包括 Android

    至于换语言能“解决”这些锅,本质上只是它们在标准库里面帮忙擦屁股而已。


    「为什么开发环境就不能默认支持这些情况呢,难道还影响兼容性?」

    开发环境当然可以默认支持这些情况,正常 POSIX 环境、正常 MSVC 环境直接写程序调用标准库 API 都没问题。
    没做到默认支持,很多时候完全是疏忽 (MSYS MinGW),或者是怕麻烦、赶进度(Android 5.0~6.0)。


    后半部分

    1 、若是 OS Level 的限制,编程语言本身能做的事情其实很有限。如果 OS 本身没解决 2038 问题,只要系统关机、重新开机,系统时间直接就是乱的,再完善的编程语言都没办法强行掰回来。
    若 OS Level 已经解决了 2038 问题,那么无论是 C 还是 C++,都不需要担心这种事。

    2 、纯 POSIX 可以。跨平台跨到 MSYS MinGW 的话,按理说 MSYS MinGW 应当处理好相应转换(像是背后处理编码调用带 W 的 API 、检测目标 Windows 有没有启用 UTF-8 区域选项),但这就不是普通使用者可以强制要求的了。

    3 、这就有点霸道了,别说 C 语言、C++,哪怕是 Python 都没法如此保证。

    4 、单纯“不拒绝使用”的话,那还是不需要担心。如果想要更高要求达到“表现一致”,那就不太可能了。
    Linux 的 IPV6_V6ONLY 默认为 false ,而 BSD 和 macOS 还有 Windows 的 IPV6_V6ONLY 默认是 true 。
    OpenBSD 更是搞起了内部限制,无论 IPV6_V6ONLY 设成什么值,它都按照 true 处理。

    5 、类似 2

    6 、支持近十年出厂的系统很合理。但硬件??这可不是编程语言可以掌控的吧,这是 OS 和驱动程序的责任啊。
    adoal
        17
    adoal  
       11 小时 7 分钟前   ❤️ 1
    文件系统和其它需要 text label 的 API 支持 Unicode 用什么模式只是一种选择而已。Unix 世界为了兼容标准 C 库的字符串 0 结尾语义而选择了 UTF-8 locales ,Windows 为了不破坏已有的 MBCS locales 里的编码语义而选择了用双模 API ,本来就是不同理念,各有优缺点。没理由 POSIX 的做法比 Windows 更正确或更“标准”。
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   Solana   ·   903 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 20:21 · PVG 04:21 · LAX 13:21 · JFK 16:21
    ♥ Do have faith in what you're doing.