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

M1平台C++调用remotezip下载文件触发段错误问题求助

M1平台C++调用remotezip下载文件段错误修复

问题背景

  • 代码适配目标:从.plist文件提取待下载文件路径,调用Python工具remotezip完成下载,剥离路径前缀后保存到指定目标文件夹
  • 故障表现:下载zip包非根目录的bss文件时触发段错误,zip根目录下的Manifest.plist下载正常,正常运行的代码片段如下:
    system((std::string("remotezip ") + zip.link + " " + "Manifest.plist ").c_str());
  • 已知工具特性:remotezip仅支持传入完整路径(调用示例:remotezip google.com /files/random/bss),调用时会自动创建路径对应的层级目录

故障代码

std::string BSS(std::string board){

//Working Path for Download 
chdir((std::string("WorkD_") + identifier + "_" + version).c_str());

std::ifstream Manifest("Manifest.plist");
 while(getline(Manifest, bss.path)) {

//Select the one matching with Board input.

  if(bss.path.find(board) != std::string::npos) {
   for(int i = 0; i < 4000 && getline(Manifest, bss.path); i++) {
    if(bss.path.find("BSS.")!= std::string::npos) {
     Manifest.close();
      bss.path.erase(0, 14);
       for(int y = 0; y < bss.path.size(); y++) {
        if(bss.path[y] == '<') {
         bss.path.erase(y);

//Remote zip work only if the path is complete like remotezip google.com /files/random/bss and it will also mkdir files and random..I believe this is the problem.
         
          system((std::string("remotezip") + zip.link + " " + bss.path).c_str());
           bss.path.erase(0, 13);
            bss.name = bss.path;
        }
       }
      }
     }
    }
   }
  return bss.name;
  }

根因定位

  1. 命令拼接错误直接触发崩溃:下载Manifest时"remotezip "尾部带空格,拼接bss路径时写为std::string("remotezip") + zip.link,remotezip和服务器链接之间无空格,最终生成的是非法shell命令。M1(ARM64)平台对非法指令的内存访问校验远严于x86平台,system执行非法命令时的内存越界会直接触发段错误,x86平台下可能因内存布局侥幸不崩溃。
  2. 文件流操作触发未定义行为:在getline遍历循环内部直接调用Manifest.close(),但外层while、内层for的循环条件仍会对已关闭的文件流执行getline操作,属于C++标准明确的未定义行为,在ARM架构上极易触发崩溃。
  3. 硬编码路径偏移存在越界风险:代码固定执行erase(0,14)、erase(0,13)截取路径,若读取到的字符串长度小于硬编码偏移值,会直接触发std::out_of_range异常,无异常捕获时进程直接终止。
  4. 系统调用无校验放大故障范围:chdir、文件打开、system调用均未做返回值校验,若目录不存在、权限不足、命令执行失败,后续逻辑会在非法状态下继续运行,触发随机崩溃。另外使用相对路径调用chdir,remotezip自动创建子目录后,后续函数调用的相对路径会失效,直接找不到Manifest.plist文件。

修复方案

  • 修正命令拼接逻辑,所有参数间保留空格,建议先将完整命令存入临时变量,方便排查
  • 调整文件流操作逻辑:找到目标路径后先跳出所有读循环,再关闭文件流,禁止在循环遍历过程中关闭正在读取的流
  • 移除所有硬编码的字符串偏移,通过字符串查找定位截取位置,截取前先校验查找结果合法性,避免字符串越界
  • 所有系统调用增加返回值校验,出错直接返回,避免在非法状态下执行后续逻辑;工作目录建议使用绝对路径,避免chdir相对路径导致的路径错乱
  • M1平台适配补充:调用remotezip时建议写工具的绝对路径,避免M1默认shell的PATH环境变量与x86 Rosetta环境差异导致找不到命令

修复后参考代码

std::string BSS(std::string board){
    // 建议替换为绝对路径拼接工作目录,避免相对路径chdir异常
    std::string work_dir = "WorkD_" + identifier + "_" + version;
    if (chdir(work_dir.c_str()) != 0) {
        return "";
    }

    std::ifstream Manifest("Manifest.plist");
    if (!Manifest.is_open()) {
        return "";
    }

    std::string line;
    std::string target_full_path;
    bool board_matched = false;
    const std::string path_prefix = "<string>"; // 对应plist标签前缀,替换原硬编码的14位偏移
    const size_t prefix_len = path_prefix.size();

    while (getline(Manifest, line)) {
        if (!board_matched) {
            if (line.find(board) != std::string::npos) {
                board_matched = true;
            }
            continue;
        }

        size_t bss_pos = line.find("BSS.");
        if (bss_pos != std::string::npos) {
            // 定位路径起始位置
            size_t path_start = line.find(path_prefix);
            if (path_start == std::string::npos) break;
            path_start += prefix_len;
            // 定位XML标签结束位置
            size_t path_end = line.find('<', path_start);
            if (path_end == std::string::npos) break;
            
            target_full_path = line.substr(path_start, path_end - path_start);
            break;
        }
    }
    Manifest.close();

    if (target_full_path.empty()) {
        return "";
    }

    // 补全命令参数间的空格,修正原拼接错误
    std::string download_cmd = "remotezip " + zip.link + " " + target_full_path;
    int cmd_ret = system(download_cmd.c_str());
    if (cmd_ret != 0) {
        return "";
    }

    // 按最后一个路径分隔符截取文件名,替换原硬编码的13位偏移
    size_t last_slash_pos = target_full_path.rfind('/');
    std::string bss_name = (last_slash_pos == std::string::npos) 
        ? target_full_path 
        : target_full_path.substr(last_slash_pos + 1);

    return bss_name;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 23:51:21