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

C++ 创建 zip 压缩包遇到的内存问题分析 -

  •  
  •   xuelang ·
    selfboot · 190 天前 · 1558 次点击
    这是一个创建于 190 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在日常的 C++ 后台开发工作中,很少会动态生成 Zip 包,所以对 C++ 的 libzip 并不熟悉。最近刚好有个场景,需要将后台生成的一份数据压缩为一个 Zip 包以便下载。这里其实之前已经有生成 Zip 包的代码,只是需要在 Zip 包里面增加一个文件。本来是一个简单的需求,但是实现中遇到了一个诡异的问题,解压生成的 Zip 包里,里面文件开头部分有错乱。

    C++ 内存问题排查:创建 Zip 压缩包,解压后内容错乱

    包含完整的:

    1. 问题复现
    2. 问题排查
    3. GDB 验证
      • 添加调试符号
      • 定位读内存位置
    4. 总结
    24 条回复    2023-10-23 09:38:09 +08:00
    araraloren
        1
    araraloren  
       190 天前
    Why not using tar ball, it is simpler than zip.
    xuelang
        2
    xuelang  
    OP
       190 天前
    @araraloren 之前历史协议就是定的 zip ,改的话需要很多地方适配
    okakuyang
        3
    okakuyang  
       190 天前 via iPhone
    是不是字符编码问题导致的呢?纯英文会不会有问题?
    ysc3839
        4
    ysc3839  
       190 天前 via Android   ❤️ 1
    省流:foreach 遍历时没加引用,把数据拷了一份,然后添加到 libzip 的结构中,循环过后数据被释放,但是 libzip 之后还会读这些数据,于是就出问题了。
    xuelang
        5
    xuelang  
    OP
       190 天前
    @ysc3839 哈哈哈,是够省流。
    xuelang
        6
    xuelang  
    OP
       190 天前
    @okakuyang 刚开始还真怀疑是编码问题,不过很容易就排除了。可以看下帖子提到的文章,里面有全部分析过程
    03
        7
    03  
       190 天前
    试过 address sanitizer 吗,似乎是典型场景
    maokabc
        8
    maokabc  
       190 天前 via Android
    之前给 libzip 做过 jni 封装,给 source 添加数组数据时自己 malloc 一次(然后不管它,zip_close 时会释放 source ,source 释放时又会释放内部 in/out)。
    Jirajine
        9
    Jirajine  
       190 天前 via Android
    多写点 rust 你会对接口的生命周期要求很敏感。
    xuelang
        10
    xuelang  
    OP
       190 天前
    @03 嗯,应该也能分析出来。不过我没试
    xuelang
        11
    xuelang  
    OP
       190 天前
    @maokabc libzip 的接口文档也写的不咋地
    xuelang
        12
    xuelang  
    OP
       190 天前
    @Jirajine rust 没用过,可以详细说下为啥会对接口生命周期要求敏感?
    cnbatch
        13
    cnbatch  
       190 天前   ❤️ 1
    其实可以用 libarchive 嘛,连微软都用
    最起码的,它的文档够清晰
    ysc3839
        14
    ysc3839  
       190 天前 via Android
    @cnbatch libarchive 感觉太大了,支持一堆格式,能配置只支持某种格式吗?
    cheng6563
        15
    cheng6563  
       190 天前   ❤️ 1
    @xuelang 因为 rust 可以说就是为了解决生命周期问题而生的。。
    Jirajine
        16
    Jirajine  
       190 天前 via Android   ❤️ 1
    @xuelang #12 你去试试就知道了,rust 对 cpp 程序员完全是无痛的。
    rust 的引用把生命周期包含在类型系统当中,你遇到的这个问题放 rust 里就是编译时错误,rust 写多了再用回裸指针没了编译器保护反而也会格外关注生命周期的正确性。
    Kumo31
        17
    Kumo31  
       190 天前   ❤️ 1
    @xuelang #12 Rust 相当于在编译期做内存管理,你这个 case 会编译不过
    cnbatch
        18
    cnbatch  
       190 天前   ❤️ 1
    @ysc3839 那就要自己裁剪了,没办法配置成只支持某种格式
    libarchive 原本只是 FreeBSD 的内部库,只不过开发团队单独提取出来给大家用,这么来看的话不太可能提供靠配置选格式支持的功能
    我在 FreeBSD 编译过使用 libarchive 的程序,发现这个库确实是内置的

    Windows 的话,我发现自 2023 年 9 月更新后,Win11 内置了 archiveint.dll ,位置是 C:\Windows\System32\archiveint.dll ,或许链接到这个 DLL 有助于降低 exe 的大小(具体能不能我也不知道,还没试)
    ysc3839
        19
    ysc3839  
       190 天前 via Android
    @cnbatch 不考虑链接 Windows 自带的 dll ,因为要支持老系统
    xuelang
        20
    xuelang  
    OP
       190 天前
    @Kumo31 编译期内存管理,有点厉害。那内存泄露啥的也不会有了,怪不得一个哥们说 rust 还挺好用的
    xuelang
        21
    xuelang  
    OP
       190 天前
    @cnbatch 嗯,感谢推荐,文档清晰太重要了
    maokabc
        23
    maokabc  
       188 天前 via Android
    @xuelang 不咋的别用就行了,命名一坨屎,很多地方需要看源码才清楚,用它就是为了那个修改 zip 。
    xuelang
        24
    xuelang  
    OP
       187 天前
    @maokabc 我们也就简单用来创建一个 zip 包,其他地方也没怎么用过。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1682 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 16:35 · PVG 00:35 · LAX 09:35 · JFK 12:35
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.