Я бы использовал двухэтапный подход. Как правило, большой процент выходных строк будет ниже определенного порога, и только несколько будут больше.
Стадия 1, используйте статический буфер разумного размера, например 4K. Поскольку snprintf()
может ограничивать количество записываемых символов, вы не получите переполнение буфера. То, что вы вернете из snprintf()
, будет количеством символов, которое написал бы , если бы ваш буфер был достаточно большим.
Если ваш вызов snprintf()
возвращает менее 4K, используйте буфер и выйдите. Как уже говорилось, подавляющее большинство звонков должны просто делать это.
Некоторые этого не сделают, и тогда вы перейдете на этап 2. Если вызов snprintf()
не помещается в буфер 4K, вы, по крайней мере, теперь знаете, насколько большой буфер вам нужен.
Выделите, с malloc()
, достаточно большой буфер, чтобы удержать его, а затем snprintf()
снова поместите в этот новый буфер. Когда вы закончите с буфером, освободите его.
Мы работали над системой за несколько дней до snprintf()
и получили тот же результат, подключив дескриптор файла к /dev/null
и используя fprintf()
с этим. Всегда гарантировано, что / dev / null будет принимать столько данных, сколько вы дадите, поэтому мы на самом деле получим из этого размер, а затем выделим буфер при необходимости.
Имейте в виду, что не все системы имеют snprintf()
(например, я понимаю, что это _snprintf()
в Microsoft C), поэтому вам, возможно, придется найти функцию, которая выполняет ту же работу, или вернуться к решению fprintf /dev/null
.
Также будьте осторожны, если данные можно изменить между проверкой размера snprintf()
и фактическим snprintf()
в буфере (т. Е. Для потоков). Если размеры увеличатся, вы получите повреждение переполнения буфера.
Если вы следуете правилу, что данные, переданные функции, принадлежат этой функции исключительно до ее передачи, это не будет проблемой.