【问题标题】:String format works in fprintf but doesn't work in sprintf, gives segmentation fault字符串格式在 fprintf 中有效,但在 sprintf 中无效,导致分段错误
【发布时间】:2011-08-04 11:14:05
【问题描述】:
fprintf(fp,"IP: %d:  %.*s\n",
        ip, 
        strstr(strstr(p->data, "User-Agent:"),"\n") - strstr(p->data, "User-Agent:"),
        strstr(p->data, "User-Agent: ") );
    fclose(fp);

大家好,正如你所看到的,在上面的语句中,我试图从一个包含整个 http 数据包数据的 char 指针中注销用户代理头。问题是,在摆弄字符串格式之后,我想出了这种 %.*s 格式,它可以让我动态选择要打印到文件的字符数,然后打印它们。代码基本上在做的是,首先,它打印一个 int,然后传递从“User-Agent:”出现到下一个出现换行符的字符数,然后开始传递该数量的字符在“User-Agent:”开始的地方,从整个数据包数据字符串开始。我知道这一切都很混乱,但它工作正常。除了它在 sprintf 中不起作用。

请保存我所有的硬词!任何帮助表示赞赏!

    char *stat;
    sprintf(stat,"%.*s\0",
        strstr(strstr(p->data, "User-Agent:"),"\n") - strstr(p->data, "User-Agent:"),
        strstr(p->data, "User-Agent: ")) ;

【问题讨论】:

  • 对您使用相同的参数调用相同的strstr 3 次感到羞耻。你知道,这是一个相当昂贵的功能。
  • @Jan:但话说回来,过早的优化是万恶之源。不编写这样的复制粘贴代码的一个更好的论点是它不那么健壮且难以维护。
  • @Paul R:是的,可维护性也是一个很好的论据。至于“过早优化”,嗯,过早优化是为了未经证实的好处而使代码变得更复杂的东西,但这会使代码更简单,更易读。
  • 为什么不像:char *ua_start = strstr(p->data, "User-Agent: "); char *ua_end = strchr(ua_start, '\n'); sprintf(stat, "%.*s\0", ua_end-ua_start, ua_start);(未经测试)。
  • 如果您修复此代码以在标头格式错误时不崩溃,则需要对strstr 进行更慢、更丑、更笨重的调用来进行检查。为了 Cthulu 的缘故,请制作一些适当的临时变量来存储所需的位置/长度!

标签: c segmentation-fault printf


【解决方案1】:

您没有为stat 分配内存。试试

char *stat = malloc(MAXLEN);
snprintf(stat, MAXLEN, ...);
 ^              ^

【讨论】:

    【解决方案2】:

    当您使用 sprintf 时,您需要写入一个字符数组。您正在写入一个未初始化的指针。

    试试这个:

    char stat[200];
    sprintf(stat, etc...
    

    【讨论】:

    • 我认为数组与 char 指针是一样的,就将它传递给函数而言。这就是为什么我这样做的原因,但我意识到了这一点,并最终纠正了它。这正是我所做的,甚至选择了相同的数字(200)。
    【解决方案3】:

    好吧,您正在尝试将数据写入未初始化的未分配随机内存位置。现在这不可能了。

    要么做:

    char stat[SUFFICIENTLY_LARGE_NUMBER];
    snprintf(stat, SUFFICIENTLY_LARGE_NUMBER, ...);
    

    或:

    char *stat = malloc(SUFFICIENTLY_LARGE_NUMBER);
    snprintf(stat, SUFFICIENTLY_LARGE_NUMBER, ...);
    

    并确保“SUFFICIENTLY_LARGE_NUMBER”的字节数足以让字符串适合,而且不会过大。

    PS:snprintf,因为您的格式不包括长度限制。如果是这样,sprintf 是可以的,但永远不要使用无限 %ssprintf。您的 %.*s 虽然正式受到限制,但还不够,因为表达式会愉快地返回超过分配缓冲区的大小,因此您需要再次检查以避免超出它。

    【讨论】:

    • 感谢您的解释以及 sprintf 和 snprintf。我从来不知道 snprint 甚至存在。感谢您的帮助!
    猜你喜欢
    • 2021-06-16
    • 1970-01-01
    • 2019-05-13
    • 2013-04-16
    • 1970-01-01
    • 2020-08-12
    • 2015-01-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多