2016-09-25 2 views
0

Я писал свою собственную библиотеку ncurses, и вдруг я нашел в GDB, что snprintf() вернула длину, большую, чем я указал. Является ли это определенным поведением или моей ошибкой? (Воспроизводимая) фрагмент кода заключается в следующем:snprintf() overflows указанная длина

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) 

Программа выводит мусор в конце строки. Как вы можете видеть, переменная len, возвращаемая из snprintf(), указывает, что функция напечатала больше, чем разрешенный размер 72. Является ли это ошибкой или моей ошибкой? Если это поведение определено, то почему snprintf() сообщает, что он будет печатать не более n символов. Очень вводящий в заблуждение и заявление о склонности к ошибкам. Мне нужно будет написать собственный snprintf(), чтобы решить эту проблему.

+1

'snprintf()' не возвращает количество символов, которые он написал, обязательно - он возвращает номер, который он * написал бы, если бы у него было достаточно места для распечатки всей отформатированной строки. Возвращаемое значение может быть использовано для определения того, насколько крупнее сделать ваш буфер, если он не был достаточно большим с первой попытки. – Dmitri

ответ

4

На самом деле (из «человек snprintf»):

Если выход был урезан из-за этого ограничения, то возвращаемое значение есть число символов (за исключением завершающего нулевого байта), который будет иметь был написал до финальной строки , если достаточно места было доступно.

+1

http://man7.org/linux/man-pages/man3/printf.3.html#RETURN_VALUE – melpomene

Смежные вопросы