#c #arduino #string-formatting #heap-memory #esp32
#c #arduino #форматирование строк #куча-память #esp32
Вопрос:
Я использую функцию storePrintf для форматирования строк (погуглил) — она работает нормально, но на 3-й или 4-й день я вижу следующую ошибку:
[E][ssl_client.cpp:33] _handle_error(): [start_ssl_client():199]: (-17040) RSA - The public key operation failed : BIGNUM - Memory allocation failed
упрощенный код показывает порядок вызовов функций
void setup() {
Serial.begin(115200);
}
char *buf ;
char *storePrintf(const char *fmt, ...)
{
va_list arg;
va_start(arg, fmt);
size_t sz = snprintf(NULL, 0, fmt, arg);
buf = (char *)malloc(sz 1);
vsprintf(buf, fmt, arg);
va_end(arg);
return buf;
}
void loop() {
String s = storePrintf("==========================: ml = %.2f, val = %dn", 0.12, 2);
Serial.println("s = " s);
free(buf);
delay(2000);
}
// this works well, but if code has a lot of calls to storePrintf with free(buf) gets error
Я полагаю, что выделение памяти не удалось из-за того, что никогда не вызывается free(buf);
после выделения памяти для buf.
когда я пытаюсь вызвать free(buf);
непосредственно после вызова storePrintf(..)
в какой-то момент появляется другая ошибка:
CORRUPT HEAP: Bad tail at 0x3ffdb993. Expected 0xbaad5678 got 0xbaad5600 assertion "head != NULL" failed
Помогите, пожалуйста, исправить эту проблему,
Комментарии:
1.
snprintf
иvsprintf
не делайте то же самое, чтобы размер для выделения мог быть неправильным. Попробуйте заменить вызов наsnprintf
сvsnprintf
.2.
snprintf
не принимаетva_list
, а скорее «обычные»prinft
аргументы. Ваша программа демонстрирует неопределенное поведение, передавая аргумент, тип которого не соответствует спецификатору формата. Вы, вероятно, ищетеvsnprintf
3. Кроме того,
va_list
является однопроходным, его недопустимо повторно использовать. Либо вызовитеva_start
еще раз, либо используйтеva_copy
для его клонирования перед первым использованием.4. Кстати, вам нужно позвонить
free()
или толькоdelete
после того, как вы позвонилиmalloc()
илиnew
.CORRUPT HEAP
означает, что память, на которую указывает указатель, не выделяется в куче. Всякий раз, когда вы назначаете указатель, напримерchar*
, без вызоваmalloc()
илиnew
, он сохраняется в стеке, а не в куче. Так что вам не нужно звонитьfree()
илиdelete
.