Why does the same vsnprintf code output differently on Windows (MSVC) and Unix (Clang)

你说的曾经没有我的故事 提交于 2021-02-16 18:51:15

问题


On Unix (Clang 3.8.1), this code outputs:

6: 32

8: a8e

On Windows (MSVC 19.00.24215.1), this code outputs:

6: 12345

6: a12345e

#include <iostream>
#include <stdarg.h>

static std::string getFormattedString(const char* fmt, va_list ap) {
  int count = vsnprintf(NULL, 0, fmt, ap) + 1;
  std::cout << count << ": ";
  if (count <= 0) { return "unable to format message"; }

  std::string result = std::string(count, '\0');
  if (vsnprintf(&result[0], count, fmt, ap) < 0) { return "error";}

  return result;
}

static std::string getFormattedString(const char* fmt, ...) {
  va_list ap;
  va_start(ap, fmt);
  std::string result = getFormattedString(fmt, ap);
  va_end(ap);
  return result;
}

int main(int argc, char *argv[]) {
  std::cout << getFormattedString("%d", 12345).c_str() << "\n";
  std::cout << getFormattedString("a%de", 12345).c_str() << "\n";

  return 0;
}

Interestingly, they both get the correct count, but on my Linux and OS X machines, this code outputs an incorrect result. What's causing this? Have I incurred UB somewhere?


回答1:


As @RaymondChen said in the comments, vsnprintf modifies ap. If you want to reuse the va_list, you have to make a copy with va_copy:

static std::string getFormattedString(const char* fmt, va_list ap) {
    va_list ap2;
    va_copy(ap2, ap);
    int count = vsnprintf(NULL, 0, fmt, ap) + 1;
    std::cout << count << ": ";
    if (count <= 0) { return "unable to format message"; }

    std::string result = std::string(count, '\0');
    if (vsnprintf(&result[0], count, fmt, ap2) < 0) { return "error";}
    std::cout << result.size() << ' ' << strlen(result.c_str()) << '\n';

    return result;
}

This will use the original list twice, and produce the correct result.



来源:https://stackoverflow.com/questions/41855571/why-does-the-same-vsnprintf-code-output-differently-on-windows-msvc-and-unix

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!