【问题标题】:sprintf_s crashessprintf_s 崩溃
【发布时间】:2011-05-05 03:35:43
【问题描述】:

我偶尔在 sprintf_s 执行以下代码时发生崩溃。这段代码工作了很多年,没有任何问题。当我在下面的语句中给出 strcat_s 和 sprintf_s 的大小时,没有出现崩溃。这可能是什么原因?

strcat_s(sztmpCurrDate,100,sztmpCurrTime); sprintf_s(sztmpCurrDate,100,"%s:%0.3d",sztmpCurrDate,curTime.wMilliseconds););

char sztmpCurrDate[100] = "";
char sztmpCurrTime[100] = "";
SYSTEMTIME curTime;
GetLocalTime(&curTime); 
GetLocalTime(&curTime); 
GetDateFormat(LOCALE_USER_DEFAULT,
                                DATE_SHORTDATE,
                                &curTime,
                                NULL,
                                sztmpCurrDate,
                                100);

GetTimeFormat(LOCALE_USER_DEFAULT,
                          TIME_FORCE24HOURFORMAT,
                          &curTime,
                          "HH':'mm':'ss",
                          sztmpCurrTime,
                          100);

strcat_s(sztmpCurrDate," ");
strcat_s(sztmpCurrDate,sztmpCurrTime);
sprintf_s(sztmpCurrDate,"%s:%0.3d",sztmpCurrDate,curTime.wMilliseconds);

【问题讨论】:

  • 您是否使用 ..._s 版本,因为您的代码没有像我预期的那样传递缓冲区的大小。
  • 有一个模板化版本的 sprintf_s 可以使用固定大小的缓冲区。
  • sprintf_s 有 _s 后缀,这意味着它不安全... ;)

标签: c++ winapi


【解决方案1】:

来自documentation for sprintf_s

如果在重叠的字符串之间发生复制,则行为未定义。

您的代码:

sprintf_s(sztmpCurrDate,"%s:%0.3d",sztmpCurrDate,curTime.wMilliseconds);

从源复制到目标sztmpCurrDate。此外,您还没有指定目标字符串的大小,这是sprintf_s 所要求的(我不知道您的代码是如何编译的)。试试:

sprintf_s(sztmpCurrDate + strlen(sztmpCurrDate), 100-strlen(sztmpCurrDate),
          ":%0.3d",curTime.wMilliseconds);

由于您使用的是 C++,因此更好的方法是使用 std::string,这样您就不必担心这种 C 字符串操作错误。

【讨论】:

    【解决方案2】:

    语法错误!!!

    sprintf_s 的第二个参数是缓冲区的长度,当程序崩溃时,你提供了指向 C 字符串 (char *) 的指针。这绝对是语法错误。

    编译器可能发出了警告,但遗憾的是让它过去了。这是因为 sprintf_s 需要三个参数 + 可变数量的参数。在您的错误情况下,您提供了三个参数,因此编译器很满意,但他将您的“格式字符串”视为“参数数量”,将 sztmpCurrDate 视为“格式字符串”。

    如果您使用任何其他具有固定数量参数的函数并且您提供的参数少于需要,这将是一个编译错误。

    【讨论】:

      【解决方案3】:

      您可能使用的版本不正确:

      sprintf_s(sztmpCurrDate,"%s:%0.3d",sztmpCurrDate,curTime.wMilliseconds);

      应该是:

      int slen = strlen(sztmpCurrDate) + 1;

      sprintf_s(sztmpCurrDate, slen, "%s:%0.3d",sztmpCurrDate,curTime.wMilliseconds);

      请参阅此sprintf_s 了解更多信息。

      【讨论】:

        【解决方案4】:

        代码工作正常,代码不正确。

        sprintf(sztmpCurrDate,"%s:%0.3d",sztmpCurrDate,curTime.wMilliseconds);
        

        改写为

        sprintf(&sztmpCurrDate[strlen(sztmpCurrDate)],"%0.3d",curTime.wMilliseconds);
        

        对于家庭作业,请告诉我们为什么.....

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-11-02
          • 1970-01-01
          • 1970-01-01
          • 2011-11-22
          • 2021-05-14
          相关资源
          最近更新 更多