свободная куча esp32, форматирование строк

#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 .