Что вызывает повреждение кучи в моем методе?

Итак, я выследил раздражающее повреждение кучи одним методом.

DWORD gdwCounter = 0;

TCHAR* GetName(const TCHAR* format, size_t len)
{
    len += (snprintf(NULL, 0, "%lu", gdwCounter) * sizeof(TCHAR));
    TCHAR *c = (TCHAR*)malloc(len);
    _stprintf_s(c, len, __TEXT("%s%lu"), format, gdwCounter);
    return c;
}

Чтобы убедиться, что я нашел правильный метод, я попытался изменить его и просто скопировать буфер «формата», который он передает в качестве параметра в выходной буфер. Повреждение кучи исчезло, и все снова стало хорошо.

Я решил посмотреть документацию snprintf и _stprintf_s.

Предполагается, что snprintf возвращает необходимые символы без завершающего нуля символа, чтобы фактически распечатать ваш буфер во втором вызове.

Мой параметр len уже содержит полный размер (с завершающим нулем символом) format.

Также я не смог найти намеков на то, что не так в документации _stprintf_s.

Так что же я упускаю?

Изменить: после дальнейшего тестирования я обнаружил, что _stprintf_s вызывает ошибку, так как snprintf возвращает правильный размер.


person James    schedule 14.12.2019    source источник
comment
Вы выделяете буфер, достаточно большой, чтобы напечатать в него gdwCounter как long unsigned, а затем также напечатать в него формат. Другими словами, вы должны использовать mallc len + strlen формата.   -  person Uri Raz    schedule 14.12.2019
comment
Я вызываю GetName следующим образом: GetName(_T(String), sizeof(_T(String))); Не должен sizeof(_T(String)) + (snprintf(NULL, 0, %lu, gdwCounter) * sizeof(TCHAR)); хватит и для формата и для gdwCounter?   -  person James    schedule 14.12.2019
comment
На дворе 2019 год. TCHAR уже устарел к моменту выхода библиотеки Unicode для Windows 98 более 20 лет назад. Почему вы используете TCHAR?!?!   -  person Dai    schedule 14.12.2019


Ответы (1)


TCHAR* GetName(const TCHAR* format, size_t len)
{
    len += snprintf(NULL, 0, "%lu", gdwCounter);
    TCHAR *c = (TCHAR*)malloc(len*sizeof(TCHAR));
    _stprintf_s(c, len, __TEXT("%s%lu"), format, gdwCounter);
    return c;
}

_stprintf_s принимает "Максимальное количество символов для хранения" вместо максимального количества байтов.

person James    schedule 14.12.2019