【问题标题】:sprintf crashes due to %s in the argument variablesprintf 由于参数变量中的 %s 而崩溃
【发布时间】:2013-09-23 06:03:50
【问题描述】:

我有一个 sprintf 命令,由于参数变量中的 %s 而崩溃。除了用 %% 转义参数字符串之外,建议的解决方法是什么。

char* s="abc%sabc";
char a[100];
sprintf(a,"The message is : %s",s);

任何帮助将不胜感激。

【问题讨论】:

  • 有什么问题?上面的代码应该可以工作。
  • 如果你只使用 c,你可以使用 strcat 例如a[100]="The message is : ";strcat(a,"abc%sabc");
  • @mvp 这是一个非常了不起的错误,他们到底是怎么弄错的? BTW %s 格式不应该解释被替换的字符串,因为它是完全错误的,与安全无关。
  • @mvp 你能提供一些关于这个错误的参考吗?我的 Linux 发行版上的上述代码没有任何问题。
  • 你能提供一个SSCCE吗?我的意思是一些可以证明问题的东西,但它是如此完整,以至于我们可以将它粘贴到一个文件中并构建并运行它。

标签: c++ c printf format-specifiers


【解决方案1】:

不要使用printf 打印任意字符串。使用puts 或格式化字符串:

char const *evil;

// Bad:
printf(evil);

// Good:
puts(evil);
fputs(evil, stdout);

// Acceptable:
printf("%s", evil);

请注意,“坏”版本不仅在理论上在某些陈旧的计算机科学方面很糟糕,而且由于%n-like 格式处理,它实际上可以立即被利用来执行任意代码和泄露数据。

【讨论】:

  • 但这就是 OP 正在做的事情。有问题的%s出现在evil中,而不是格式字符串中!
  • @Angew:是的。我不了解 OP 的实际问题,所以我只是给出了一些一般性建议,如果正确遵循这些建议,应该可以使字符串处理没有错误。
【解决方案2】:

您的示例对我有用:http://ideone.com/ZnsiZZ

只需使用std::string:

#include <string>  // for std::string

std::string s = "abc%sabc";
std::string a = "The message is : " + s;

或者如果您需要连接其他类型,例如整数:

#include <string>  // for std::string
#include <sstream> // for std::stringstream

std::string s = "abc%sabc";
int i = 42;
std::stringstream sstr( "The message is : " );
sstr << s << "" << i;
std::string a = sstr.str(); // a = "The message is : abc%abc 42"

【讨论】:

    【解决方案3】:

    我只会留在 C 领域(不使用 C++)。

    对我来说,这段代码不会崩溃并打印出abc%abc

    #include <stdio.h>
    int main() {
        char* s="abc\%sabc";
        printf("The message is: %s\n", s);
    }
    

    但是这段代码会打印abcabc(没有%)并且有时会崩溃:

    #include <stdio.h>
    int main() {
        char* s="abc\%sabc";
        char a[100];
        sprintf(a, "The message is: %s\n", s);
        printf(a);      // <-- %s is interpolated in printf!
    }
    

    您的问题很可能是您尝试使用printf 打印由sprintf 创建的字符串 - 这会进行第二次插值并导致所有麻烦。

    解决方案始终使用puts() 打印由sprintf() 创建的字符串。

    【讨论】:

    • 我在问题中提供了示例代码。实际上,我的函数需要...并且我使用以下行 va_list arglist; va_start(arglist, cFormat); vsnprintf(logCharString,sizeof(logCharString)-2, cFormat, arglist); logCharString[sizeof(logCharString)-2]=0; va_end(arglist);
    【解决方案4】:

    使用std::string,你的问题就会解决:

    #include <sstream> //include this
    
    std::string s = "abc%sabc";
    std::string a = "The message is : " + s;
    

    如果您想使用非字符串值,例如int,那么std::stringstream 会帮助您:

    int s = 100; //s is int now!
    std::stringstream ss("The message is : ");
    ss << s;
    std::string a = ss.str(); //a is => The message is : 100
    

    希望对您有所帮助。

    【讨论】:

    • 这里的stringstream没用。
    • @Rapptz:现在它很有用。 :-)
    【解决方案5】:

    OP 很可能使用printf(a) 打印任意字符串a

    char* s="abc%sabc";
    char a[100];
    sprintf(a,"The message is : %s",s);
    // My guess is that OP follows with
    printf(a);  // This causes the error.
    

    这会失败,因为 a"The message is : abc%sabc"。作为printf()格式,该函数需要另一个参数,因为a 中的%s - 它没有给出并且未定义的行为(UB)结果。

    OP 应该改为

    printf("%s", a);
    // or
    puts(a);
    

    【讨论】:

      猜你喜欢
      • 2011-03-12
      • 2015-09-08
      • 2011-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多