-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Handle strings in the sketch - heap problem. #222
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I did a little investigation on this. While it is possible to move strings off the heap, the attribute to do this is not compatible with the use like F() nor PSTR(). It requires that target be global in scope and a variable. will work
will not
|
I now have a grasp on how to fix it. Its going to take a bit as a lot of original Arduino abstraction for it was removed from the code base and I have to add it all back to get it to work. |
@Makuna could you please drop into our chat at https://gitter.im/esp8266/Arduino to discuss the changes required? |
Hello, Then I will change: PROGMEM const char WSDL[] = "/webservice/SimpleSwitch?xsd=1">/xsd:import/xsd:schema<message name="switchOnFor3Minutes"><part name="parameters" element="tns:switchOnFor3Minutes">.........................Long string"; Output: So there should be some way, how to store the bytes to the flash and read it directly from flash. Especially for the Webserver. |
I have solution. It is in progress and a pull will be posted with the fixes. The current PROGMEM just mapped to ram. It will work just like Arduino does today, storing strings into the instruction ".irom.text" section. It will support F(), PSTR(), PROGMEM, Print extensions, String extensions, and str*_P methods. |
#236 pending with fixes |
this was merged in |
Work: Not Work: In file included from C:\Program Files (x86)\Arduino\hardware\esp8266com\esp8266\cores\esp8266/Arduino.h:212:0, |
This is invalid syntax and use of F(). It will not compile when targeting AVR either. F is not a string class that does string manipulation, use String for that. It is simply a way to annotate string literals so they are stored in rom rather than ram. The simple fix to your example is
But I suspect there is more to your case than your example? The following will work and is supported.
|
Ok thanks. I fixed it i have define to FLASH ROM error: invalid conversion from 'const __FlashStringHelper*' to 'uint8_t {aka unsigned char}' [-fpermissive] How do I do that |
how are you using webcss? What are you passing it to? Provide the code for the call. please read up on the differences between F() and PSTR() in the Arduino documentation. |
webss is my css file send client. ok now I'm looking at. thank you so much. |
Hello, great work!!! Working well - PROGMEM and also F() macro. I have now a lot of stack free:)))) |
Just a question: I know, that AVR is doing this: If I have two same strings in the sketch will it occupy only one space in the program flash? I.e.: Will this occupy 5 bytes or 10 bytes? In case of AVR and arduino, it will take only 5 bytes (4+1 null terminator.) |
Hello, seems, something is wrong. I have modified my sketch to use everywhere the F() macro, and when I tried to compile, the compiler freeze and never finish: C:\RH\Arduino1.6.4/hardware/tools/esp8266/xtensa-lx106-elf/bin/xtensa-lx106-elf-g++ -D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ -IC:\RH\Arduino1.6.4/hardware/tools/esp8266/sdk//include -c -Os -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -std=c++11 -MMD -DF_CPU=80000000L -DARDUINO=10604 -DARDUINO_ESP8266_ESP01 -DARDUINO_ARCH_ESP8266 -DESP8266 -IC:\RH\Arduino1.6.4\hardware\esp8266com\esp8266\cores\esp8266 -IC:\RH\Arduino1.6.4\hardware\esp8266com\esp8266\variants\generic -IC:\RH\Arduino1.6.4\hardware\esp8266com\esp8266\libraries\ESP8266WiFi\src -IC:\RH\Arduino1.6.4\hardware\esp8266com\esp8266\libraries\ESP8266WebServer\src -IC:\RH\Arduino1.6.4\hardware\esp8266com\esp8266\libraries\EEPROM C:\Users\gregorro\AppData\Local\Temp\build3042939131809121947.tmp\SimpleSwitch.cpp -o C:\Users\gregorro\AppData\Local\Temp\build3042939131809121947.tmp\SimpleSwitch.cpp.o What could be wrong??? |
How much memory are you using for strings? |
What do you mean? You mean how long the strings are in the sketch? The size of the ino file is around 64 kb, so the strings could have around 30 Kb. |
Unfortunately the tool chain does not seem to "pool" constant string instances. Every definition will create and consume flash memory. So it seems for now that you need to manually make sure you have no duplicates. |
@robertgregor could you copy a single line of code each of how you define a string and how you use it? |
I have attached a Ino that will cause the compiler to "puke". In the middle of all those prints, there is a comment that if you comment out a line, it works (clean load of the file). So that is the edge of memory size that causes problems I suspect. the compile just endlessly repeats this with verbose compile option turned on.
|
This isn't the compiler, looks more like the Java preprocessor part has failed (the one which makes a .cpp out of .ino). |
@igrr You are correct. If I move the strings into a cpp, the issue that was demonstrated with the compiling seemly hanging is gone. Further, if I create enough strings, I will run into a nice error message about exceeding flash. So all is good.
|
HelIo, it seems that this construction hangs the compiler or preprocessor: |
@robertgregor What type is html? |
html is String object |
@robertgregor Please enter a unique issue for this problem; I can repro it.
That line should read...
|
I can get F() to work inside functions and my heap goes right down. I can't get it to work on a global variable though. I've tried
could someone give an example of how to store a large global string in flash? appreciated.:) |
Please list the failure case example code. |
1.6.1-esp8266-1-1055-gcf89c32 ok so i can't reproduce the crashing bit not sure what i did there. |
although i get a reset if i try if i use me-no-dev, suggested that i use |
Don't use the String class if you want avoid heap and use str*_P methods if you are using PSTR or PROGMEM or __FlashStringHelper if you are using F(). The String class copies everything into heap. Make sure you understand the difference between a C/C++ string and a String class. Please review the Arduino reference for progmem, PSTR, F. Again, minimum but complete code examples help. The Serial.write() method doesn't work with flash strings. Serial.print will if you define your flash string the way it wants.
|
Guys,
but as soon as I'm trying to do some Did I forgot something ? Here complete example
|
Did you check how printf was defined? This will work.
or if you happen to have a lot of them in a row, a more efficient way
|
@Makuna |
Ivan. Is this fixed ? I've been looking at things like const char *pointerToStaticString = "ABDCE"; and currently, this doesn't get compiled into the ROM it gets compile into the RAM const char staticString[6]="ABCDE"; doesn't get compile into ROM either. I presume this is either a gcc settings (compile or linker switch options) or a linker file issue Is that what your fix is that is staged for release ? Or an I looking at a different problem ? |
const char arrays are not expected to go into flash by default, because special care is required to read byte-size data from flash (i.e. pgm_read_byte). However you may use progmem macros to move stuff into flash. |
Umm OK. I thought that the ESP8266 was the same sort of architecture as on the STM32 where if we declare a either a char array or pointer to const string, these go into Flash But perhaps because the flash is external to the ESP8266 this affects the way the compiler and linker can be configured. |
Flash is memory-mapped into the address space in the ESP8266. However due to the way this is implemented in hardware, this memory has alignment restrictions — all reads have to be dword-aligned. So while you can modify the linker script to place all strings into flash, normal C library functions (like strcpy, strstr and others) will not be able to work with such strings. Reading individual bytes from strings placed into flash requires something similar to |
Thanks for the explanation. I have some large strings which are SVG graphics, which I don't want to put into SPIFFS because I need to update them as part of the firmware via OTA. So I'll need to look at the PROGMEM stuff, as currently they are getting put into RAM which is becoming a problem as I add more of them. Anyway. Thanks again Roger |
PROGMEM is an abstraction, albeit not the best way to do this; but it has rooted itself into Arduino and pretty much became the way to do this if you want to write standard Arduino code. Relying on const to do this for some chips is a mistake, especially if you write a library. |
Thanks for sharing your knowledge, guys. I am new to Arduino and was puzzled when sprintf() refused to take F() constants. Rather it did, but the result was including some random text from RAM instead of my constant. |
Hello, it seems, that all the strings used in the sketch are going to the heap. I have a sketch which is using ESP8266WebServer. In each handler, I am using the Strings to output. Now I've reached the situation, that if I put any more Strings in the sketch, the heap is full. It is very strange, thus based on the hint I am now doing this:
static const char XSD_SW_1[] = "blablba-bigstring";
Then in the handler method:
server.send(200, "text/xml", "");
WiFiClient client = server.client();
client.write(&XSD_SW_1[0], sizeof(XSD_SW_1)-1);
But looks like that that const is a part of the heap, because if I will do XSD_SW_1[] = ""; then everything is OK. If I leave big - aroung 1400 characters - maximum buffer of the Webserver write method, my sketch doesn't work at all - seems, it will even not start correctly.
Is there any way, how to tell to compiler, that the strings should stay on flash and should be read, when it is needed? In arduino, there is for this purpose the F() macro or PROGMEM directive. But I belive, this is avr specific.
The text was updated successfully, but these errors were encountered: