Confused, htmlbodystring.replace() doesn't work all the time

Hi guys,

I have problems with my code, building a website body.

The variable "String htmlContent" contains the whole html body including some placeholders like %%JAVASCRIPT%% and %%IPADDRESS%% etc.
"String htmlJS" contains some javascript code

With every web request from a client I build the website content and replace a lot of placeholders with content of other variables. Sometimes this fails JUST for the htmlJS String.

See screenshot attachment.

Example code:

  htmlContent.replace("%%JAVASCRIPT%%", htmlJS);
  htmlContent.replace("%%IPADDRESS%%", ipaddress);
  htmlContent.replace("%%OTHERPLACEHOLDERS%%", otherstrings);
  httpServer.send(200, "text/html", htmlContent);

I assumed it has something to do with heap, so I tried to debug it with the following code:

  uint32_t heap = system_get_free_heap_size();
  Serial.println("###");
  Serial.println(heap);
  Serial.println(htmlJS.length());
  Serial.println(htmlContent.length());
  htmlContent.replace("%%JAVASCRIPT%%", htmlJS);   //this line is sometimes just ignored
  Serial.println(heap);
  Serial.println(htmlJS.length());
  Serial.println(htmlContent.length());
  Serial.println("###");
  httpServer.send(200, "text/html", htmlContent);

Results in:

###
14720
5566
8565
14720
5566
14117
###

if it works.

And in:

###
13984
5566
8565
13984
5566
8565
###

if it doesn't work.

Any clue what's going wrong?

Thanks in advance

Stefan

Do not use the "String" class on arduino's, it may be causing memory corruption and it is impossible to predict how it allocates memory which is sparse.

It is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. This can happen after the program has been running perfectly for some time. Just use cstrings - char arrays terminated with '\0' (NULL).

...R

The printing of heap in below is useless; it will give the same result as the earlier one.

 htmlContent.replace("%%JAVASCRIPT%%", htmlJS);   //this line is sometimes just ignored
  Serial.println(heap);

You will have to modify it to

 htmlContent.replace("%%JAVASCRIPT%%", htmlJS);   //this line is sometimes just ignored
  heap = system_get_free_heap_size();
  Serial.println(heap);

so you get a fresh 'reading'.

Which board are you using?

Further it's possible that the symptoms show in the code that you showed but that the problem actually is in another part of the code.

"If" you do want to use 'S'trings to create websites, keep them local variable, start over every time you create a page String thePage=""; and add any pieces that you want to add sequentially. then send that as a whole and as the function is terminated the memory will be freed. It is apparently slow, but on a board with an ESP-core it is safe (enough)

sterretje:

  1. The printing of heap in below is useless; it will give the same result as the earlier one.
  2. Which board are you using?
  3. Further it's possible that the symptoms show in the code that you showed but that the problem actually is in another part of the code.
  1. sorry, of course you are right. will change it
  2. NodeMCU 1.0
  3. hmm. no clue :wink: As several people have told me not to use Strings I have one question. How can I perform this with a char array?:
String html = R"###(<html><body
   some content 
   <span style=".......">%%IP_PLACEHOLDER%%</span>
   </body></html>)###";
html.replace("%%IP_PLACEHOLDER%%", ipaddress);

I assume using sprintf?
And how would I know the correct size for the required char array? My html code is huge :wink:

Deva_Rishi:
"If" you do want to use 'S'trings to create websites, keep them local variable, start over every time you create a page String thePage=""; and add any pieces that you want to add sequentially. then send that as a whole and as the function is terminated the memory will be freed. It is apparently slow, but on a board with an ESP-core it is safe (enough)

that's actually what I do. It's not a global variable

StefanHaupt:
that's actually what I do. It's not a global variable

Then why do you use 'replace' ? just start over with a new String every time, have chunks of 'const char *' that you can use to add and add all that is beyond that with '+='

I've now "fixed" the problem by just embedding the javascript String content directly into the htmlContent String content. Originally I thought it makes sense to split both code parts into two variables. Now the merge was the easiest fix, so I went for this.