я получил следующий код (часть log
функции):Почему этот стек разбит?
/* set to 32 on purpose */
#define MAX_LOG_MSG_SZ 32
void log(const char *fmt, ...) {
....
char msg[MAX_LOG_MSG_SZ] = {0};
int nb_bytes = 0;
/* get current time */
time_t now = time(NULL);
char time_buf[32] = {0};
/* format time as `14 Jul 20:00:08`, and exactly 16 bytes */
strftime(time_buf, sizeof(time_buf), "%d %b %H:%M:%S", localtime(&now));
nb_bytes = snprintf(msg, sizeof(msg), "%s", time_buf);
va_list ap;
va_start(ap, fmt);
vsnprintf(msg + nb_bytes, MAX_LOG_MSG_SZ, fmt, ap);
va_end(ap);
....
}
Хитрость вещей при прохождении длинных параметров (сделать его больше, чем 32 байта) и изменить time_buf
на другое значение меньше, чем 32 (больше 16, например, 31), этот код приведет к разрыву стека. После минуты отладки, я изменил vsnprintf
вызывающую строку, как
vsnprintf(msg + nb_bytes, MAX_LOG_MSG_SZ - nb_bytes, fmt, ap);
и стек Smashing ушел, я думаю, что проблема исправлена.
НО: На time_buf[32]
(или другого большего размера), поэтому ошибка вызывающему
vsnprintf(msg + nb_bytes, MAX_LOG_MSG_SZ, fmt, ap);
не
бросить стек разящий? Точнее, почему msg
's разбивка стека, связанная с этим несвязанный stack (time_buf
) space?
UPDATE: это мой uname -a
выход:
Linux coanor 3.5.0-34-generiC#55-Ubuntu SMP Thu Jun 6 20:20:19 UTC 2013 i686 i686 i686 GNU/Linux
фактически, вы ошибаетесь.snprintf возвращает количество символов, которые ** были бы написаны **. Не количество успешно записанных байтов. Эта ошибка может привести к серьезным неприятностям в этом коде. (Предположим, что результирующая строка будет больше 32 и рассмотрит следующий вызов snprintf с 'MAX_LOG_MSG_SZ - nb_bytes') – junix
Я предполагаю, что они здесь одинаковы. OP копирует time_buf в msg. – bsd
Скорее всего, это верно для этого конкретного случая. Но когда я читаю ваше заявление, мне кажется, что это всегда будет так, а это не так. Вот почему я хотел отметить свой комментарий. – junix