0

I hope you all well.

Recently after view unknown crashes I decided it can be related with me messing with "heap"

After reading few sources on heaps and how it works it kind of confusing. Some sources mention that you can F() everything and it will be fine and others mention reserving space for strings with "reserve()"

I am looking for suggestions how possibly eliminate or or control?

I will post snapshot of code below where the evil "String" is used few times.

////////sending data
    senddata(String(temp), String(hum), String(dis), String(flood), String(heaterstatus), String(humidifierstatus));
    //////////sending data

void senddata(String temp1, String hum1, String dis1, String flood1, String heater1, String humid1) {   /////sending all field values in one go
  //////////sending data
  String getData = "GET /update?api_key=" + API + "&field1=" + temp1 + "&field2=" + hum1 + "&field3=" + dis1 + "&field4=" + flood1 + "&field5=" + heater1 + "&field6=" + humid1;
  sendCommand("AT+CIPMUX=1", 5, "OK");
  sendCommand("AT+CIPSTART=0,\"TCP\",\"" + HOST + "\"," + PORT, 15, "OK");
  sendCommand("AT+CIPSEND=0," + String(getData.length() + 4), 4, ">");
  esp8266.println(getData); delay(1500); countTrueCommand++;
  sendCommand("AT+CIPCLOSE=0", 5, "OK");
}
0

Yes, you could make a global String for getData and reserve space and reuse it every time the function is called. But what with String(getData.length())?

And the parameters? You create a new String for every parameter. And the function senddata doesn't take a reference to the String (String&), but it makes a new copy of each String parameter. So you create 12 small Strings with every call to this function. This is the evil of String. It does everything no matter at what cost.

And your sendCommand takes String too. That is why you can do "AT+CIPSTART=0,\"TCP\",\"" + HOST + "\"," + PORT and "AT+CIPSEND=0," + String(getData.length() + 4) as parameter to it. So every call to sendCommand creates two small Strings. That is 8. And every + on String can trigger a reallocation on heap.

Use C strings

void senddata(int temp1, int hum1, int dis1, int flood1, int heater1, int humid1) {
  char getData[256];
  snprintf(getData, sizeof(getData), "GET /update?api_key=%s&field1=%d&field2=%d&field3=%d&field4=%s&field5=%s&field6=%d",
      API, temp1, hum1, dis1, flood1, heater1, humid1);
  sendCommand("AT+CIPMUX=1", 5, "OK");
  char buff[32];
  snprintf(buff, sizeof(buff), "AT+CIPSTART=0,\"TCP\",\"%s\",%d" , HOST, PORT);
  sendCommand(buff, 15, "OK");
  snprintf(buff, sizeof(buff), "AT+CIPSEND=0,%d" , strlen(getData) + 4);
  sendCommand(buff, 4, ">");
}

void sendCommand(const char* command, const int timeout, const char* find) {

F macro optimizes memory use, by using data stored in flash memory. The snprintf_P function is a version of snprintf for format string from flash.

snprintf_P(getData, sizeof(getData), (const char*) F("GET /update?api_key=%s&field1=%d&field2=%d&field3=%d&field4=%s&field5=%s&field6=%d"),
  API, temp1, hum1, dis1, flood1, heater1, humid1);

One of the classes of my StreamLib is CStringBuilder. With it the code could be:

char getData[256];
CStringBuilder sb(getData, sizeof(getData));
sb.printf(F("GET /update?api_key=%s&field1=%d&field2=%d&field3=%d&field4=%s&field5=%s&field6=%d"),
    API, temp1, hum1, dis1, flood1, heater1, humid1);
sendCommand("AT+CIPMUX=1", 5, "OK");
char buff[32];
CStringBuilder sb2(buff, sizeof(buff));
sb2.printf(F("AT+CIPSTART=0,\"TCP\",\"%s\",%d") , HOST, PORT);
sendCommand(buff, 15, "OK");
sb2.reset();
sb2.print(F("AT+CIPSEND=0,"));
sb2.print(sb.length() + 4);
sendCommand(buff, 4, ">");
  • Hello @Juraj and thanks for getting involved. The snprintf function seems to be very interesting and suitable. I had a good look for a good guide on the function, however, limited answers. What i would like to find out is what does it mean when you use %d and %s or how they are diffent? – Tad Dec 19 '18 at 12:25
  • printf is 50 years old. cplusplus.com/reference/cstdio/printf – Juraj Dec 19 '18 at 12:42
  • Thanks for that, its a great reference. Do you know if there are any limitations to where i can use it? It seems to be that any floats cant be used? Is there any common functions that may conflict? – Tad Dec 19 '18 at 12:53
  • using printf versions takes a little more of flash memory. float support can be enabled, but it takes even more program memory. Alternative is to use my CStringBuilder class, which builds a C string using the same simple functions like Serial – Juraj Dec 19 '18 at 13:04

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.