mirror of
https://github.com/tzapu/WiFiManager.git
synced 2026-04-27 00:55:52 +03:00
[GH-ISSUE #1587] Using PROGMEM for string arrays #1355
Labels
No labels
📶 WiFi
🕸️ HTTP
Branch
DEV Help Wanted
Discussion
Documentation
ESP32
Example
Good First Issue
Hotfix
In Progress
Incomplete
Needs Feeback
Priority
QA
Question
Task
Upstream/Dependancy
bug
duplicate
enhancement
invalid
pull-request
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/WiFiManager#1355
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @dalbert2 on GitHub (Apr 14, 2023).
Original GitHub issue: https://github.com/tzapu/WiFiManager/issues/1587
Basic Infos
string arrays in wm_consts_en.h aren't being placed in PROGMEM properly
Hardware
WiFimanager Branch/Release: Master
Esp8266/Esp32: ESP8266
Hardware: ESP-12e
Core Version: 3.0.5
Description
Moving strings into PROGMEM is essential for ESP8266 where IRAM is extremely tight.
This code is incorrect (see wm_consts_en.h):
The above code places the pointers to the string constants in PROGMEM, but the string constants themselves land in RAM.
The below code shows how to put both the pointers and the strings themselves in PROGMEM:
I know this is ugly, but it works; if someone knows a prettier solution, please share it. At present, WiFiManager uses 1344 of IRAM even if you don't instantiate an instance of the class which is a problem for many applications on the ESP8266.
Settings in IDE
Sketch
Debug Messages
@dalbert2 commented on GitHub (Apr 14, 2023):
Even worse, the string constants are all declared in header files which are included by WiFiManager.h so any class or module that includes WiFiManager.h creates a copy of all of the string constants. Why are these not defined in a compilation unit (.c or .cpp)?
@tablatronix commented on GitHub (Apr 15, 2023):
What am I missing here? I am not seeing this memory waste
@dalbert2 commented on GitHub (Apr 15, 2023):
@tablatronix please see: https://arduino-esp8266.readthedocs.io/en/latest/PROGMEM.html#how-do-i-declare-arrays-of-strings-in-progmem-and-retrieve-an-element-from-it
If you do this with the string arrays, you will see free heap increase.
I also think the strings need to be moved into a separate compilation unit (e.g. wm_strings.cpp). You can still use the pre-processor to select a language and a header file to define extern references for strings needed by other compilation units. Example:
strings.h
strings.c
main.c:
Compile for english:gcc strings.c main.c
Compile for spanish: gcc strings.c main.c -DLANG_ES
@timr49 commented on GitHub (Jul 31, 2025):
I checked the contents of the compiled code in the .o, .elf and .bin files using strings(1).
When two cpp files (typically WiFiManager.cpp and the calling code) include WiFiManager.h and hence wm_strings_en.h
there are indeed multiple copies of each of the flash memory strings compiled into the .o files and linked into the .elf file. However the process that converts the .elf file to the .bin file deduplicates them such that the final executable does not contain duplicates, as observed by @tablatronix.
I checked this with both of Arduino IDE rather than PlatformIO, specifically ESP8266 3.1.2 and ESP32 3.2.0.
The WiFiManager version I used was commit
32655b7226(HEAD, origin/master, origin/HEAD, master).Per @dalbert2, usual practice would be to put only declarations in a .h file and definitions in a .cpp file. In this case, only WiFiManager.cpp needs to reference these strings, so that could be done simply by including the strings file in WiFiManager.cpp rather than WiFiManager.h and moving the few initialisations that use flash strings in WiFiManager.h from there to WiFiManagerInit() in WiFiManager.cpp. As shown above, it doesn't buy us any memory, though it would decrease compile times by some unknown amount.
@tablatronix commented on GitHub (Jul 31, 2025):
Something is wrong with the compiler if its ignoring include guards, perhaps include in the main source file and see if that changes it.
@timr49 commented on GitHub (Jul 31, 2025):
I disagree. Include guards only ever stop one .cpp file from including the same .h file more than once. They cannot stop multiple .cpp files from each including the same .h file once each, which is what is happening.
As suggested, including the strings file in WiFiManager.cpp rather than WiFiManager.h is preferable.
@tablatronix commented on GitHub (Aug 4, 2025):
I can try it, i do not recall the decision to use headers, I think arduino auto included .cpp in folder and it was an issue