【问题标题】:sprintf_s and access violationsprintf_s 和访问冲突
【发布时间】:2020-04-07 05:21:32
【问题描述】:

我在 Windows 上使用 C/C++ 程序的 Visual Studio 中收到“0xC0000005:访问冲突读取位置错误”,并试图简化以说明我的问题。下面的代码运行得很好:

char tmp[1000];
ULONG64 val1 = 1;
sprintf_s(tmp, 1000, "%lu, %s, %s", val1, "true", "false");

但是,当我在格式中添加一个额外的 unsigned long 时,我会遇到访问冲突,如下面的代码所示:

char tmp[1000];
ULONG64 val1 = 1;
ULONG64 val2 = 2;
sprintf_s(tmp, 1000, "%lu, %lu, %s, %s", val1, val2, "true", "false");

【问题讨论】:

  • "使用 C/C++ 程序" 没有像“C/C++”这样的语言。它可以是 C、 C++。您实际上在使用哪个?一旦你有了这个问题的答案:删除你不使用的语言标签。
  • 小花絮并没有影响问题,但是从变量本身推导出缓冲区的大小而不是重复数字是非常明智的:sprintf_s(tmp, sizeof tmp, ...)。如果您更改了一个而忘记更改另一个,这可以避免不愉快的意外。
  • 该程序使用 Windows C 库,但我尽可能使用 C++,例如 std::string
  • @publicwireless 所以,然后是 C++。
  • @WeatherVane 这不是注释,而是答案!

标签: c windows visual-c++


【解决方案1】:

格式说明符 %lu 用于 unsigned long,它是 32 位而不是 MSVC 上的 64。

所以堆叠的参数被误用了,MSVC 应该对此发出警告。

您可以使用%llu 对冲,但最好使用正确的格式来保证与固定宽度变量的匹配。

如果类型是uint64_t,那么例如在使用printf 时,您应该有

printf("%" PRIu64 "\n", val1);

例如。

【讨论】:

    【解决方案2】:

    %lu 似乎不是正确的格式说明符。

    传递不正确类型的值将导致未定义的行为

    您应该改用格式说明符%I64u

    因为:

    【讨论】:

      【解决方案3】:

      您在评论中提到您希望尽可能使用 C++。然后去做,避开所有类型不安全的 C!

      #include <sstream>
      #include <string>
      
      int main()
      {
          unsigned long val1 = 1;
          unsigned long val2 = 2;
          std::ostringstream sstr;
      
          // the true/false being a bit nonsensical, but to
          // stay close to your original code
          sstr << val1 << ", " << val2 << ", " << "true" << ", " << "false";
      
          std::string tmp{ sstr.str() };
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-05-28
        • 1970-01-01
        • 2017-08-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多