String is empty after being passed to a function

Hi,

my code retrieves the content of a web page as a string and passes it on to a function. But it seems the string is suddenly empty within the function. I get the output:

07:13:51.673 -> Connect WiFi..Connected!
07:13:55.136 -> HTTP request successfully!
07:13:55.499 -> A:65204
07:13:55.499 -> B:0

Thanks for help!


#include <WiFi.h>
#include <HTTPClient.h>

const char* ssID = ""; // <- insert your WiFi settings
const char* ssPW = ""; // <- insert your WiFi settings

bool ConnectWiFi() {
  Serial.print("Connect WiFi");
  WiFi.begin(ssID, ssPW);
  for (int i = 0; i < 50; i++) {  // 50 x 200 ms = 10 sec
    Serial.print(".");
    if (WiFi.status() == WL_CONNECTED) {
      Serial.println("Connected!");
      return true;
    } else if (WiFi.status() == WL_NO_SSID_AVAIL) {
      Serial.println("Error: No signal!");
      return false;
    }
    delay(200);
  }
  Serial.println("Error: Too many attempts!");
  return false;
}

String GetHTML(String url) {
  String content = "";
  HTTPClient http;
  http.begin(url);
  int httpCode = http.GET();
  if (httpCode > 0) {
    Serial.println("HTTP request successfully!");
    content = http.getString();
  } else {
    Serial.println("Error on HTTP request!");
  }
  http.end();
  return content;
}

void MyFunction(String mystring) {
  Serial.print("B:");
  Serial.println(mystring.length());
}

void setup() {
  Serial.begin(115200);
  delay(500);
  Serial.println();
  if (ConnectWiFi()) {
    String content = GetHTML("https://www.wetteronline.de/wetter/berlin");
    Serial.print("A:");
    Serial.println(content.length());
    MyFunction(content);
  }
}

void loop(){};

A 64K character string passed as a parameter? Could you simply be running out of stack space and the runtime went "I am NOT passing that!"?

1 Like

Sorry, new in C++. I came from python and there I have already transferred strings with several gigabytes as parameters. What is the problem with more than 64 k in C++? I use an ESP32.

Yeah, that's not happening on a microcontroller. Welcome to the land of limited resources.

What board? How much RAM?

ESP32. The compiler says after compiling: "there are 280684 Bytes free for local variables, 327680 Bytes max"

With sharing the variable it works:

void MyFunction(String &mystring) {
  Serial.print("B:");
  Serial.println(mystring.length());
}

Can I monitor the use of memory while execution?

And you're burning almost half of that in two Strings. Strings that I imagine are being assembled byte by byte in the library. Dollars to donuts you've fragmented the living daylights out of the heap, leaving myriad tiny chunks of memory that can't be reused because garbage collection and heap consolidation aren't a thing in micro land. You've simply run out of usable RAM.

Which is the long winded way of saying: "The String class should be avoided like the plague for this very reason."

Are the strings saved in unicode (2 Bytes per char)?

You'd have to examine the library to find out.

Here's the hard limit

#ifdef BOARD_HAS_PSRAM
  enum {
    CAPACITY_MAX = 3145728
  };
#else
  enum {
    CAPACITY_MAX = 65535
  };
#endif

With a few exceptions, if any allocation fails, it does so silently. It is suspicious that the GET resulted in a string just under the limit: A:65204. Is that how big it actually is? The URL doesn't seem to work for me; I get

   <p>Die angeforderte Seite kann nicht angezeigt werden.</p>
   <br>
   <p>The requested page cannot be displayed.</p>

No, they're a slightly intelligent bunch of bytes; assumed in some cases elsewhere to be UTF-8. But not in the class itself; e.g. length is the number of bytes, not Unicode characters.

  String x = "È É Ê Ë";
  Serial.println(x.length());  // 4 * 2 + 3 --> 11, not 7
1 Like

Thanks! It seems HTTPClient.getString() only delivers 65204 bytes anyway, no matter how large the source is (see limits).

There are functions in Esp.h, such as:

  ESP.getHeapSize();
  ESP.getFreeHeap();
  ESP.getMinFreeHeap();
  ESP.getMaxAllocHeap();

I use these to dispay in the 'stats' page of a couple of ESP32 projects with a web UI, e.g.

Why are you passing the String object by value instead of by reference? As is, it's attempting to make an extra copy of the String.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.