From c4d03bf1b7ff73d0d92c8d4826e14faef7440e5e Mon Sep 17 00:00:00 2001 From: MaPaLo76 <72209721+MaPaLo76@users.noreply.github.com> Date: Sun, 1 Mar 2026 12:11:00 +0100 Subject: [PATCH] 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) --- include/config.h | 6 +++--- platformio.ini | 8 +------- src/web_server.cpp | 26 +++++++++++++++++++++----- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/include/config.h b/include/config.h index 608db4e..2a58915 100644 --- a/include/config.h +++ b/include/config.h @@ -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); \ diff --git a/platformio.ini b/platformio.ini index d9b3b34..e0b656e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -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 diff --git a/src/web_server.cpp b/src/web_server.cpp index 350d14b..fe876cb 100644 --- a/src/web_server.cpp +++ b/src/web_server.cpp @@ -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'; } }