【问题标题】:Sprintf crashing my programSprintf 使我的程序崩溃
【发布时间】:2016-12-23 22:26:54
【问题描述】:

我只是尝试使用 sprintf 连接一些字符串,但我遇到了这个问题, 我不明白为什么我的程序在 C 中使用 sprintf 会崩溃。为什么这段代码会运行?

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char* dateTime = malloc(16*sizeof(char));

    printf("Date: %s\n", __DATE__);
    printf("Time: %s\n", __TIME__);

    sprintf (dateTime, "%s, %s\0", __DATE__, __TIME__);

    printf("%s", dateTime);
    free(dateTime);

    return 0;
}

这个不是吗?

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char* dateTime = malloc(16*sizeof(char));

    //printf("Date: %s\n", __DATE__);
    //printf("Time: %s\n", __TIME__);

    sprintf (dateTime, "%s, %s\0", __DATE__, __TIME__);

    printf("%s", dateTime);
    free(dateTime);

    return 0;
}

【问题讨论】:

  • 检查sprintf的返回值。
  • 很好奇,为什么 16char* dateTime = malloc(16*sizeof(char));
  • 请注意,字符串末尾的\0 是多余的; C 编译器会自动在字符串末尾添加一个空字节。

标签: c pointers printf


【解决方案1】:

在我的编译器上,您创建的字符串长度为 21 个字符 (Dec 23 2016, 23:29:57),因此您基本上为字符串分配了太少的字节。

你得到未定义的行为。所以它在没有printf 语句的情况下崩溃,并且可以使用它们,因为计算机没有做完全相同的事情,但它仍然是错误的。

顺便说一句,您可以通过这样做安全地实现您想要的:

const char *dateTime= __DATE__ " " __TIME__;

因为__DATE____TIME__ 已经是字符串宏。预处理器可以在编译时进行连接。

如果您想计算所需的字符数,可以使用 snprintfNULL 缓冲区(仅限 c99):

使用零 bufsz 和缓冲区空指针调用 snprintf 有助于确定包含输出所需的缓冲区大小:

const char *fmt = "sqrt(2) = %f";
int sz = snprintf(NULL, 0, fmt, sqrt(2));
char buf[sz + 1]; // note +1 for terminating null byte
snprintf(buf, sizeof buf, fmt, sqrt(2));

http://en.cppreference.com/w/c/io/fprintf

【讨论】:

    【解决方案2】:

    看来您的缓冲区对于sprintf 来说太小了:

    char* dateTime = malloc(16*sizeof(char));
    

    __DATE____TIME__ 总是占用超过 15 个字节(不包括 NUL 字符)。越过数组边界写入会导致未定义的行为。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-22
      • 1970-01-01
      • 2011-05-26
      相关资源
      最近更新 更多