fix(stability): Heap-Leak durch String/JsonDocument-Objekte behoben

- web_server.cpp: static String _logBuf -> char[6001] im BSS-Segment
  Jeder LOG_I/E/D-Aufruf loeste String-Reallokation aus (~280 Bytes/min Drift)
  Fix: memmove-basierter Ring-Puffer, kein malloc/free mehr
- mqtt_client.cpp: JsonDocument in publishHeartbeat() und _doPublishSession()
  durch snprintf-JSON ersetzt (kein ArduinoJson-Heap-Pool alle 60 s)
- config.h: LOG-Puffer von 200 auf 320 Bytes erhoeht (Truncation fix)
- platformio.ini: CORE_DEBUG_LEVEL wieder auf 1 (war 3 fuer Heap-Diagnose)
This commit is contained in:
MaPaLo76 2026-03-01 12:11:00 +01:00
parent 7935dfbba4
commit c4d03bf1b7
3 changed files with 25 additions and 15 deletions

View File

@ -129,20 +129,20 @@ static inline const char* _logTs() {
// Log-Makros: Nachricht formatieren, auf Serial ausgeben und in Web-Log-Puffer schreiben.
#define LOG_I(tag, fmt, ...) do { \
char _lb[200]; \
char _lb[320]; \
snprintf(_lb, sizeof(_lb), "[%s][I][%s] " fmt, _logTs(), tag, ##__VA_ARGS__); \
Serial.println(_lb); \
webLogForward(_lb); \
} while(0)
#define LOG_E(tag, fmt, ...) do { \
char _lb[200]; \
char _lb[320]; \
snprintf(_lb, sizeof(_lb), "[%s][E][%s] " fmt, _logTs(), tag, ##__VA_ARGS__); \
Serial.println(_lb); \
webLogForward(_lb); \
} while(0)
#if CORE_DEBUG_LEVEL >= 3
#define LOG_D(tag, fmt, ...) do { \
char _lb[200]; \
char _lb[320]; \
snprintf(_lb, sizeof(_lb), "[%s][D][%s] " fmt, _logTs(), tag, ##__VA_ARGS__); \
Serial.println(_lb); \
webLogForward(_lb); \

View File

@ -23,7 +23,7 @@ build_flags =
-DCORE_DEBUG_LEVEL=1 ; 0=keine, 1=Fehler, 3=Info, 5=Verbose
-DARDUINO_LOOP_STACK_SIZE=8192
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
-DFIRMWARE_VERSION='"1.2.0"' ; Semantic Versioning hier erhöhen bei neuem Release
-DFIRMWARE_VERSION='"1.2.1"' ; Semantic Versioning hier erhöhen bei neuem Release
lib_deps =
majicDesigns/MD_Parola @ ^3.7.3
majicDesigns/MD_MAX72XX @ ^3.5.1
@ -155,8 +155,6 @@ monitor_speed = 115200
monitor_echo = yes
board_build.partitions = min_spiffs.csv
build_src_filter = -<*> +<../test_sketches/test_wifi.cpp> +<../src/wifi_connector.cpp>
build_flags =
-DCORE_DEBUG_LEVEL=3
lib_deps =
tzapu/WiFiManager @ ^2.0.17
majicDesigns/MD_MAX72XX @ ^3.5.1
@ -177,7 +175,6 @@ monitor_speed = 115200
monitor_echo = yes
build_src_filter = -<*> +<../test_sketches/test_laser_tracker.cpp> +<../src/display_manager.cpp> +<../src/settings.cpp> +<../src/laser_tracker.cpp>
build_flags =
-DCORE_DEBUG_LEVEL=1
-Wno-cpp
lib_deps =
majicDesigns/MD_MAX72XX @ ^3.5.1
@ -196,7 +193,6 @@ monitor_speed = 115200
monitor_echo = yes
build_src_filter = -<*> +<../test_sketches/test_display_manager.cpp> +<../src/display_manager.cpp>
build_flags =
-DCORE_DEBUG_LEVEL=1
-Wno-cpp
lib_deps =
majicDesigns/MD_MAX72XX @ ^3.5.1
@ -224,7 +220,6 @@ monitor_echo = yes
board_build.partitions = min_spiffs.csv
build_src_filter = -<*> +<../test_sketches/test_mqtt_client.cpp> +<../src/settings.cpp> +<../src/display_manager.cpp> +<../src/laser_tracker.cpp> +<../src/wifi_connector.cpp> +<../src/mqtt_client.cpp>
build_flags =
-DCORE_DEBUG_LEVEL=1
-Wno-cpp
lib_deps =
majicDesigns/MD_MAX72XX @ ^3.5.1
@ -263,7 +258,6 @@ build_src_filter =
+<../src/mqtt_client.cpp>
+<../src/web_server.cpp>
build_flags =
-DCORE_DEBUG_LEVEL=1
-Wno-cpp
-DASYNC_TCP_SSL_ENABLED=0
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1

View File

@ -28,13 +28,29 @@ static AsyncWebSocket* _wsPtr = nullptr;
// webLogForward() läuft auf Core 1 (Arduino loop) kein Task, kein Queue,
// kein Core-Problem. Browser pollt GET /log-data alle 2 s.
static const size_t LOG_BUF_MAX = 6000;
static String _logBuf = "";
// Fester BSS-Puffer keinerlei Heap-Verwendung (kein Arduino-String!)
static char _logBuf[LOG_BUF_MAX + 1] = {0};
static size_t _logBufLen = 0;
void webLogForward(const char* msg) {
_logBuf += msg;
_logBuf += '\n';
if (_logBuf.length() > LOG_BUF_MAX) {
_logBuf = _logBuf.substring(_logBuf.length() - LOG_BUF_MAX / 2);
size_t msgLen = strlen(msg);
size_t addLen = msgLen + 1; // +1 für '\n'
// Wenn Nachricht nicht reinpasst: hintere Hälfte per memmove behalten
if (_logBufLen + addLen >= LOG_BUF_MAX) {
size_t keep = LOG_BUF_MAX / 2;
if (keep < _logBufLen) {
memmove(_logBuf, _logBuf + (_logBufLen - keep), keep);
_logBufLen = keep;
} else {
_logBufLen = 0;
}
_logBuf[_logBufLen] = '\0';
}
if (_logBufLen + addLen < LOG_BUF_MAX) {
memcpy(_logBuf + _logBufLen, msg, msgLen);
_logBufLen += msgLen;
_logBuf[_logBufLen++] = '\n';
_logBuf[_logBufLen] = '\0';
}
}