【问题标题】:Multiplatform build - snprintf fails in C多平台构建 - snprintf 在 C 中失败
【发布时间】:2021-05-01 21:25:12
【问题描述】:

我正在学习 C 并试图确保我的代码是可移植的。为此,我在 Mac(ARM、PPC、Intel)、Linux(ARM、PPC、PA-RISC)和 HP-UX(PA-RISC)上构建。 为了确保我有一种简单的方法来输出简单的图形,我使用了 GLUT。

我有以下代码和功能:

GLfloat white[3] = { 1.0, 1.0, 1.0 };
GLfloat red[3] = { 1.0, 0.0, 0.0 };
GLfloat green[3] = { 0.0, 1.0, 0.0 };

void printText(char *text, const GLfloat colour[3], float posX, float posY) {
    glColor3fv (colour);
    glRasterPos2f(posX, posY); //define position on the screen
      
    while(*text){
      glutBitmapCharacter(GLUT_BITMAP_8_BY_13, *text++);
    }
}

void GLprintTextAndInteger (char *text, int value, float colour[3], float posX, float posY) {
    int length = snprintf(NULL, 0, "%s %i", text, value);
    char *stringToPrint = malloc(length + 1);
    snprintf(stringToPrint, length + 1, "%s %i",text,value);
    printText(stringToPrint,colour,posX,posY);
    free(stringToPrint);
}

void GLprintTextAndLong (char *text, long value, float colour[3], float posX, float posY) {
    int length = snprintf(NULL, 0, "%s %ld", text, value);
    char *stringToPrint = malloc(length + 1);
    snprintf(stringToPrint, length + 1, "%s %ld", text, value);
    printText(stringToPrint,colour,posX,posY);
    free(stringToPrint);
}

我这样称呼,例如:

GLprintTextAndInteger("sample text", int whatever, white, -0.98f, 0.1f);
GLprintTextAndLong("sample text", long whatever, white, -0.98f, 0.0f);
printText("some text",white,-0.98f,-0.1f);

当我在 HP-UX 上构建时,同时使用 HP 的编译器和 GCC,当我运行程序时,只有 printText 有效。 GLprintTextAndInteger 和 GLprintTextAndLong 什么都不做(或者他们可能工作,但是是黑色的,然后我看不到输出)。代码在所有平台上构建时都没有任何警告。它在 Linux 和 Mac 上运行良好,适用于所有架构。

有什么建议吗?

编辑:

在故障排除过程中,我发现如果我更换:

int length = snprintf(NULL, 0, "%s %i", text, value);

int length = 40;

它工作正常。为什么 snprintf 失败了?

【问题讨论】:

  • 希望您使用的是 freeglut 而不是 opengl 中的 glut。 stackoverflow.com/q/15613978/1216776
  • 谢谢@stark。不过,我不明白这有什么关系。我的目标实际上是使用系统附带的官方支持的库。我认为我遇到的问题与 C 相关,而不是与 GLUT 相关。
  • 您确定在 HP-UX 上拥有并使用符合 POSIX.1-2001 或 C99 的 C 库环境吗?引用手册页:“关于 snprintf() 的返回值,SUSv2 和 C99 相互矛盾:当使用 size=0 调用 snprintf() 时,SUSv2 规定未指定的返回值小于 1,而 C99 允许 str 为 NULL在这种情况下,并给出返回值(一如既往)作为在输出字符串足够大的情况下将写入的字符数。POSIX.1-2001 及更高版本将其 snprintf() 规范与 C99 对齐。 "
  • @derhass 你在这里做点什么。在运行 snprintf(NULL, 0, "%s %i", text, value); 后,我放置了一个 printf() 来打印 int 长度。我在 HP-UX 下得到 0,在其他地方得到字符串的实际长度。我仍然是一个初学者,所以我什至不知道在哪里查找,但我会深入研究文档。
  • 嗯,您描述的行为符合 Single Unix Specification v2。它只是不符合 C99 或 POSIX.1-2001。归根结底,这就是存在 GNU autotools 之类的东西的原因——它允许您为 Unix 风格之间的各种差异编写测试,并在必要时使用单独的实现。例如,请参阅 jhweiss.de/software/snprintf.html 以了解您可以将其添加到项目中的 C99 兼容 snprintf 实现。

标签: c opengl powerpc hp-ux pa-risc


【解决方案1】:

根据snprintf(3s) 的手册页(参见https://www.unix.com/man-page/hpux/3s/snprintf/):

默认情况下,如果 maxsize 小于格式化的字符数,则返回负值。在 UNIX 2003 标准中 环境(参见standards(5))它返回将被写入缓冲区s的字节数,不包括终止的null 字节,如果 maxsize 足够大。

UNIX 2003 标准仅在 HP-UX 11iv3 (11.31) 上受支持,如果您像这样编译:

$ export UNIX_STD=2003
$ make/cc/whatever

这是我用来验证这一点的测试程序:

root@hpvm01:~/t$ cc -o s s.c
root@hpvm01:~/t$ ./s
r=0
root@hpvm01:~/t$ UNIX_STD=2003 cc -o s s.c
root@hpvm01:~/t$ ./s
r=6
root@hpvm01:~/t$ cat s.c
#include <stdio.h>

int main()
{
  int r = snprintf(NULL, 0, "hello\n");

  printf("r=%d\n", r);
}

所以我希望您使用的是 11.31 而不是更早的版本。在这种情况下,snprintf 的开源版本可能会有所帮助:http://hpux.connect.org.uk/hppd/hpux/Development/Libraries/snprintf-2.2/

【讨论】:

    猜你喜欢
    • 2015-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-27
    • 2018-04-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多