snprintf()溢出指定的长度

时间:2016-09-25 18:24:34

标签: c printf

我正在编写自己的ncurses库,突然我在GDB中发现snprintf()返回的长度大于我指定的长度。是这个定义的行为还是我的一些错误? (可重现的)代码段如下:

niko: snippets $ cat snprintf.c
#include <unistd.h>
#include <stdio.h>

char *example_string="This is a very long label. It was created to test alignment functions of VERTICAL and HORIZONTAL layout";

void snprintf_test(void) {
    char tmp[72];
    char fmt[32];
    int len;
    unsigned short  x=20,y=30;

    snprintf(fmt,sizeof(fmt),"\033[%%d;%%dH\033[0m\033[48;5;%%dm%%%ds",48); 
    len=snprintf(tmp,sizeof(tmp),fmt,y,x,0,example_string);
    write(STDOUT_FILENO,tmp,len);
}


int main(void) {
    snprintf_test();
}
niko: snippets $ 

现在我们使用调试信息进行编译并运行:

niko: snippets $ gcc -g -o snprintf snprintf.c
niko: snippets $ gdb ./snprintf -ex "break snprintf_test" -ex run
.....
Reading symbols from ./snprintf...done.
Breakpoint 1 at 0x40058e: file snprintf.c, line 10.
Starting program: /home/deptrack/depserv/snippets/snprintf 

Breakpoint 1, snprintf_test () at snprintf.c:10
10      unsigned short  x=20,y=30;
Missing separate debuginfos, use: dnf debuginfo-install glibc-2.22-16.fc23.x86_64
(gdb) s
12      snprintf(fmt,sizeof(fmt),"\033[%%d;%%dH\033[0m\033[48;5;%%dm%%%ds",48); 
(gdb) print sizeof(fmt)
$1 = 32
(gdb) print sizeof(tmp)
$2 = 72
(gdb) s
13      len=snprintf(tmp,sizeof(tmp),fmt,y,x,0,example_string);
(gdb) print fmt
$3 = "\033[%d;%dH\033[0m\033[48;5;%dm%48s\000\000\000\000\000"
(gdb) print example_string
$4 = 0x4006c0 "This is a very long label. It was created to test alignment functions of VERTICAL and HORIZONTAL layout"
(gdb) s
14      write(STDOUT_FILENO,tmp,len);
(gdb) print len
$5 = 124
(gdb) print sizeof(tmp)
$6 = 72
(gdb) 

程序在字符串的末尾输出垃圾。如您所见,从snprintf()返回的len变量表明该函数的打印超过了允许的大小72.这是一个错误还是我的错误?如果定义了此行为,那么为什么snprintf()docs会说它最多会打印n个字符。非常误导和容易出错的声明。我将不得不编写自己的snprintf()来解决这个问题。

1 个答案:

答案 0 :(得分:4)

实际上(来自&#34; man snprintf&#34;):

  

如果输出是          由于此限制而截断,则返回值为数字          字符(不包括终止空字节)本来就是          写入到最终字符串如果有足够的空间

相关问题