Короче говоря: vsnprintf повредил мою кучу под HP-UX 11.11.
vsnprintf был введен в C99 (ISO / IEC 9899: 1999) и «эквивалентен snprintf со списком переменных аргументов» (§7.19.6.12.2), snprintf (§7.19.6.5.2): «Если n равно нулю , ничего не написано ".
Что ж, HP UX 11.11 не соответствует этой спецификации. Когда 2-й аргумент == 0, аргументы записываются в конце 1-го аргумента .. что, конечно, портит кучу (я не выделяю пробел при maxsize == 0, учитывая, что ничего не должно быть записано ).
HP справочные страницы неясны («Ответственность за доступность хранилища лежит на пользователе»), ничего не сказано о случае maxsize == 0 . Хорошая ловушка .. по крайней мере, раздел ПРЕДУПРЕЖДЕНИЙ на странице руководства должен предупреждать пользователей, совместимых со стандартом std ..
Это яйцо / курица pb: vnsprintf является вариативным, поэтому для «ответственности пользователя» за обеспечение достаточного объема памяти «ответственность пользователя» должна сначала знать, сколько места необходимо. И лучший способ сделать это это вызвать vnsprintf со вторым аргументом == 0: тогда он должен вернуть количество требуемого пространства и ничего не sprintfs .. ну, кроме HP!
Одно из решений использовать vnsprintf при этом нарушении std для определения необходимого пространства: malloc на 1 байт больше в ваш буфер (1-й аргумент) и вызов vnsprintf (buf + buf.length, 1, ..). Это только помещает \ 0 в новый байт, который вы выделили. Глупо, но эффективно. Если вы находитесь в условиях wchar, malloc (sizeof ..).
В любом случае, обходной путь тривиален: никогда не вызывайте v / snprintf в HP-UX с maxsize == 0!
У меня теперь счастливая стабильная программа!
Спасибо всем, кто внес свой вклад.
Повреждение кучи через vsnprintf под HP-UX B11.11
Эта программа печатает "@@" под Linux / Cygwin / ..
Он печатает "@ fooo @" под HP-UX B11.11:
#include <stdarg.h>
#include <stdio.h>
const int S=2;
void f (const char *fmt, ...) {
va_list ap;
int actualLen=0;
char buf[S];
bzero(buf, S);
va_start(ap, fmt);
actualLen = vsnprintf(buf, 0, fmt, ap);
va_end(ap);
printf("@%s@\n", buf);
}
int main () {
f("%s", "fooo");
return 0;
}