Я портирую очень старый (> 10y) код C современным Linux. Я получаю ошибку сегментации в специально написанном vsnprintf() обертки (по-видимому, его задача состоит в том, чтобы обнаружить дубликаты выходных строк и стажер их):Как вы называете vsnprintf() безопасно?
char* strVPrintf(const String fmt, va_list ap)
{
/* Guess we need no more than 50 bytes. */
int n, size = 50;
char* p = (char*)memMalloc(size), q;
while (1) {
/* Try to print in the allocated space. */
n = vsnprintf(p, size, fmt, ap);
/* If that worked, return the string. */
if (n > -1 && n < size) {
break;
}
/* Else try again with more space. */
if (n > -1) /* glibc 2.1 */
size = n + 1; /* precisely what is needed */
else /* glibc 2.0 */
size *= 2; /* twice the old size */
p = memRealloc(p, size);
}
q = strRegister(p);
memFree(p);
return q;
}
Автор, кажется, предположил, что стандартная vsnprintf()
функции возвращает количество написанных символов и просто возвращает значение дозорного, если оно не получает достаточно места для форматирования всех аргументов. Это означает, что вы можете просто угадать размер буфера и при необходимости увеличить его.
Но в моей системе (Ubuntu 14.04, glibc 2.19) vnprintf вызывает ошибку сегментации при вызове с слишком большим количеством аргументов для предоставленного пространства. Изменилась ли семантика семьи snprintf()
, что значительно изменилось? И каков современный способ обеспечить вам достаточное пространство для буфера?
'человек vsnprintf': * Функции snprintf() и vsnprintf() не пишите больше байтов размера (включая завершающий нулевой байт ('\ 0')). Если результат был усечен из-за этого предела, возвращаемым значением является количество символов (исключая завершающий нулевой байт), которые были бы записаны в финальную строку, если бы было достаточно свободного места. Таким образом, возвращаемое значение размера или больше означает, что результат был усечен. * Эта часть программы кажется правильной. – EOF
Вы не проверяете наличие сбоев в распределении памяти. – user694733
Что такое 'String'? Я подозреваю, что это 'char *', но вы также должны предоставить эту информацию. –