首页 > 解决方案 > 在 System() 调用后打印时 printf 出现意外行为

问题描述

我有以下带有相关控制台输出的“主要”功能。

argv[1] = "C:\\Program Files (x86)\\InstallShield Installation Information\\0x041f.txt"

int main(int argc, char **argv){
    if (argc < 2)
    {
        printf("Please provide a file name with extension\r\n");
        return 1;
    }
    unsigned char buf[LEN_NORM];
    char filename[230];
    char ali_dirname[200];
    char bli_dirname[200];

    FILE *fp_obj, *fp_det, *fp_txt = fopen(argv[1], "rb");
    //dirty?
    *(argv[1] + strlen(argv[1]) + 1 - 5) = '\0';
    snprintf(ali_dirname, strlen(argv[1]) + 4, "%s/ali", argv[1]);
    snprintf(bli_dirname, strlen(argv[1]) + 4, "%s/bli", argv[1]);

    char cmd[200];
    snprintf(cmd, strlen(argv[1]) + 12, "@RD /S /Q \"%s\"", argv[1]);
    printf("cmd: %s\r\n", cmd);
    system(cmd);
    printf("cmd: %s\r\n", cmd);
}

cmd: @RD /S /Q "C:\Program Files (x86)\InstallShield 安装信息\0x041f"

文件名、目录名或卷标语法不正确。

信息\0x041f" 文件 (x86)\InstallShield 安装

控制台输出

正如您在系统调用后看到的,控制台完全损坏了。我真的不明白为什么会这样。任何想法?

编辑:感谢您的反馈,我认为 snprintf 长度是关于一个想要写入的数据的长度。“cmd”具有固定长度,即允许的最大大小。根据我在网上找到的信息,“大小”是将写入缓冲区的最大字节数(字符),所以在我的情况下,12 应该是正确的数字(我用调试器检查过,“\”是正确写入的)而不是 sizeof(cmd),我错了吗?我在所有“snprintf”案例中都尝试过“12 + 1”(4 + 1)和“sizeof”,但没有任何变化

代码在“main”中运行(我已经更新了它)

如果我删除“系统(cmd)”调用控制台输出就可以了!

标签: cwindowsprintf

解决方案


  • 一个问题:一个接一个

strlen(argv[1]) + 12是输出的预期长度,但它是应该传递给的所需大小snprintf()- 需要加一。当前代码肯定会删除'\"'打印到的最后一个字符cmd

//                                   12345678901   2
snprintf(cmd, strlen(argv[1]) + 12, "@RD /S /Q \"%s\"", argv[1]);
// better
snprintf(cmd, strlen(argv[1]) + 12 + 1, "@RD /S /Q \"%s\"", argv[1]);

这并不能很好地解释OP 输出末尾的 П\0x041f,但肯定是一个问题。


  • cmd在使用可能被截断的字符串执行系统命令之前,正确使用大小并最好测试结果。

    int len = snprintf(cmd, sizeof cmd, "@RD /S /Q \"%s\"", argv[1]);
    if (len < 0 || (unsigned) len >= sizeof cmd) {
      fprintf(stderr, "Forming `cmd` failed\n");
    } else {
      printf("cmd: %s\r\n", cmd);
      system(cmd);
    }
    

未发布的代码中可能存在其他问题。


推荐阅读