【问题标题】:msvcrt alternative for MinGW? (e.g. to get conforming snprintf)MinGW 的 msvcrt 替代品? (例如,获得一致的 snprintf)
【发布时间】:2019-08-22 07:50:16
【问题描述】:

所以这是一个有趣的...

我们有一些 C 库应该独立于平台,即使它们是在 linux 上开发的,因为它们只依赖于 ISO/IEC 9899:1999 中定义的 c 标准库。当我们用 MinGW 编译这些库时,起初一切似乎都运行良好,但今天我们发现 msvcrt 的 snprintf() 实现是braindea ......对不起,我的意思是“不兼容" 与 C99 标准中的定义。

我本以为 MinGW 会发出警告,告诉我 -std=c99 实际上并不完全受支持。因为不然,我怎么知道?

是否有任何用于 windows 的替代 c 标准库,最重要的是:MinGW 是否可以以某种方式被告知链接它而不是 msvcrt?

如果没有,我们至少需要一个列表或其他东西,以便我们检查有关 msvcrt 和 c99 的其他潜在可移植性问题。

PS: 我知道 Cygwin 和 MSYS2,但我宁愿拥有原生 Windows 二进制文件(部分原因是我们也在 Matlab 中使用我们的库)。

编辑: 抱歉,我应该更清楚地解释我对 msvcrt 的 snprintf() 的问题到底是什么。根据标准,如果输出不合适,则需要 snprintf() 输出 '\0' 作为最后一个字符。但是, msvcrt 只是不这样做,因此生成的字符串不再正确终止。我不知道为什么有人会选择以这种方式实现 snprintf(),因为对我来说只是省略 '\0' 根本没有任何意义。

我们也尝试了建议的 __USE_MINGW_ANSI_STDIO,但我想这只是修复了缺少的格式说明符?至少它似乎对我们的具体问题没有影响。

【问题讨论】:

  • @lundin:我重新打开了,因为它不再与副本匹配
  • “因为对我来说只是省略 '\0' 根本没有任何意义。” 更可怕的想法是它100% 完全有意义 这就是它以这种方式工作的原因。
  • 我无法重现该问题。请在您的问题中包含minimal reproducible example,以证明您在使用snprintf 时遇到的问题。
  • @AnttiHaapala 它仍然是重复的。哦,好吧,我会在这里发布答案......

标签: c printf mingw msvcrt crt


【解决方案1】:

标准强制snprintf 表现如下:

否则,第 n-1 个以外的输出字符是 被丢弃而不是被写入数组,并且在实际写入数组的字符末尾写入一个空字符。

msvcrt 中的snprintf 确实不是标准版本,而是此处解释的 Microsoft 版本:
Is snprintf() ALWAYS null terminating?

以下代码给出了不合规的结果:

#include <stdio.h>

int main (void)
{
  char dst[3];
  snprintf(dst, 3, "%c%c%c", 'A', 'B', 'C');

  for(size_t i=0; i<3; i++)
  {
    printf("%.2X ", dst[i]);
  }
}

我得到不符合标准的输出41 42 43。要获得标准 C,您必须在stdio.h 之前添加此

#define __USE_MINGW_ANSI_STDIO 1

现在您会得到符合要求的41 42 00

所有这些程序安全问题的根源在于微软,他们在过去 20 年中一直在其产品中使用不兼容的 C 库。

【讨论】:

  • (为了重现这个问题,我特意用一个非常旧的 Mingw 版本进行了尝试,
  • 感谢您的信息。到目前为止,我们已经尝试了 -D__USE_MINGW_ANSI_STDIO 以及 #define,但由于某种原因,我们的 MinGW (5.4) 仍然不使用标准兼容版本。我们现在将测试一个像您这样的孤立示例,以确保这一点。
  • @FelixG 如果有多个文件包含 stdio.h,可能是链接顺序出现问题。
  • @Lundin 不,没有任何 VLA。
  • @Lundin 现在可以正常工作了,很明显,当我们第一次测试它时,里面还有一些旧的 .o 文件^^。非常感谢。
【解决方案2】:

如果您需要来自 MinGW-w64 的 C99 stdio,您可以定义 __USE_MINGW_ANSI_STDIO 以便绕过 msvcrt 实现。最好通过编译器参数来定义它

-D__USE_MINGW_ANSI_STDIO

或者,您可以尝试使用设置为与新 ucrt 链接的 MinGW-w64 构建,但我不知道任何预先存在的易于使用的稳定构建以这种方式设置.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-21
    • 2014-06-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多