В приложении, над которым я работаю, средство ведения журнала использует sprintf для форматирования текста, который записывается в файл. Итак, что-то вроде:
char buffer[512];
sprintf(buffer, ... );
Это иногда вызывает проблемы, когда отправляемое сообщение становится слишком большим для выделенного вручную буфера.
Есть ли способ добиться поведения sprintf без необходимости вручную выделять память таким образом?
Обновлено: хотя sprintf - это операция C, я ищу решения типа C++ (если они есть!), Чтобы получить такое поведение ...





"средство ведения журнала использует sprintf для форматирования текста, который записывается в файл"
fprintf() не накладывает никаких ограничений на размер. Если вы можете записать текст прямо в файл, сделайте это!
Однако я предполагаю, что есть промежуточный этап обработки. Если вы знаете, сколько места вам нужно, вы можете использовать malloc(), чтобы выделить его.
Один из приемов в таких случаях - выделить буфер разумного размера (который будет достаточно большим в 99% случаев), а если он недостаточно велик, разбить данные на части, которые вы обрабатываете один за другим.
Большую часть этого преимущества можно получить, если буферизовать файл, если это возможно. По-прежнему есть накладные расходы, но, по крайней мере, вы не попадаете на диск.
В ванильной версии sprintf нет способа предотвратить перезапись данных переданного в буфере. Это верно независимо от того, была ли память выделена вручную или размещена в стеке.
Чтобы предотвратить перезапись буфера, вам необходимо использовать одну из более безопасных версий sprintf, например sprintf_s (только для Windows).
http://msdn.microsoft.com/en-us/library/ybk95axf.aspx
Можно защититься от переполнения буфера с помощью vanilla sprintf (), например sprintf (buf, "%. * s", buf_size - 1, input_string); Но это работает только для известных строк фиксированного формата.
Нет, вы не можете использовать sprintf() для выделения достаточного количества памяти. Альтернативы включают:
snprintf() для усечения сообщения - это не решит полностью вашу проблему, но предотвратит проблему переполнения буфераstd::string и ostringstream - но вы потеряете формат printf, вам придется использовать оператор <<Обратите внимание, что snprintf () сообщает вам, сколько места вам нужно, поэтому вы можете использовать его дважды, если потребуется, первый раз со статическим буфером, как показано, и второй раз с динамически выделяемым буфером.
-1 для второго предложения (удвоение размера буфера. Поскольку вы не знаете максимальную длину строки, вы не можете гарантировать, что она не переполнится, даже если вы умножите ее на миллиард).
Вы можете использовать asprintf (3) (примечание: нестандартно), который выделяет буфер для вас, поэтому вам не нужно его предварительно выделять.
Пожалуйста, отметьте доступность этой функции для разных систем, потому что это не стандартная библиотека C lib или POSIX.
В основном это Linux - вероятно, тоже BSD. Также существует vasprintf ().
Ах да, извините за это ... OP не упомянул, какая платформа, поэтому я просто выбросил ее туда. Его можно найти в Linux, BSD и Mac OS X ... теперь это стандартная часть библиотеки gnuc.
Я также не знаю версию, которая избегает выделения, но если C99 sprintfs допускает в качестве строки указатель NULL. Не очень эффективно, но это даст вам полную строку (если доступно достаточно памяти) без риска переполнения:
length = snprintf(NULL, ...);
str = malloc(length+1);
snprintf(str, ...);
Если вы используете C99, вы также можете просто использовать массив переменной длины, поэтому вместо mallocing str просто объявите его как «char str [length + 1];» после вызова snprintf. Тогда не нужно освобождать его, так как он находится в стеке.
Если вы используете среду выполнения MSVC, вы обнаружите, что snprintf возвращает отрицательное значение вместо требуемой длины. поэтому, если вам нужна требуемая длина в MSVC, вам нужно будет использовать другую функцию, _vscprintf [msdn.microsoft.com/en-us/library/w05tbk72.aspx]
доступ к файлам намного медленнее, чем доступ к памяти. Это одна из причин, почему промежуточный спринт - неплохая идея.