应该 return -1 的 sprintf 编码错误是什么?

What is an encoding error for sprintf that should return -1?

我理解 snprintf 会 return 当“发生编码错误”时的负值

但是会产生该结果的“编码错误”的简单示例是什么?

我正在使用 gcc 10.2.0 C 编译器,我尝试过格式错误的格式说明符、不合理的大字段长度数字,甚至是空格式字符串。

这与重复做类似的事情有关:

length += snprintf(...

构建格式化字符串。

如果确定 不是 到 return 负值,那可能是安全的。

将缓冲区指针前移一个负长度可能会导致它越界。但我正在寻找一个实际会发生的案例。如果存在这种情况,则可能需要增加复杂性:

length += result = snprintf(...

到目前为止,我找不到值得为检查编译器可能永远不会生成的值而增加复杂性的场景。也许你可以举一个简单的例子。

通常情况下,当发生输出错误时,您只会期望 printf 和 family 出现错误。来自 Linux 手册页:

If an output error is encountered, a negative value is returned.

因此,如果您正在输出到 FILE 并且发生某种输出错误(EPIPE、EIO),您将得到一个负值 return。对于 s[n]printf,因为没有输出,所以永远不会有负值 return。

该标准讨论了“编码错误”的可能性,但仅定义了宽字符流的含义,并指出在某些情况下字节流可能需要转换为宽字符流。

An encoding error occurs if the character sequence presented to the underlying mbrtowc function does not form a valid (generalized) multibyte character, or if the code value passed to the underlying wcrtomb does not correspond to a valid (generalized) multibyte character. The wide character input/output functions and the byte input/output functions store the value of the macro EILSEQ in errno if and only if an encoding error occurs.

这似乎意味着如果您使用 %ls%lc 格式将宽字符串或字符转换为字节,则可能会出现编码错误。不确定是否还有其他可能发生的情况。

What is an encoding error for sprintf that should return -1?

在我的机器上,"%ls" 不喜欢 0xFFFF - 当然是编码错误。

  char buf[42];
  wchar_t s[] = { 0xFFFF,49,50,51,0 };
  int i = snprintf(buf, sizeof buf, "<%ls>", s);
  printf("%d\n", i);

输出

-1

以下代码返回 -1,但与其说是编码错误,不如说是病理格式。

#include <stdio.h>

int main() {
  size_t n = 0xFFFFFFFFLLu + 1;
  char *fmt = malloc(n);
  if (fmt == NULL) {
    puts("OOM");
    return -42;
  }
  memset(fmt, 'x', n);
  fmt[n - 1] = '[=12=]';
  char buf[42];
  int i = snprintf(buf, sizeof buf, fmt);
  printf("%d %x\n", i, (unsigned) i);
  free(fmt);
  return 7;
}

输出

-1 ffffffff

当传递一个太大的尺寸时,我确实得到了令人惊讶的 -1,即使 snprintf() 只需要 6 个字节。

  char buf[42];
  int i = snprintf(buf, 4299195472, "Hello");
  printf("%d\n", i);

输出

-1

由于 方向 冲突,我能够想出一个在 *fprintf()stdout 上返回 -1 的简短示例。

#include <wchar.h>
#include <stdio.h>

int main() {
  int w = wprintf(L"Hello wide world\n");
  wprintf(L"%d\n", w);
  int s = printf("Hello world\n");
  wprintf(L"%d\n", s);
}

输出

Hello wide world
17
-1