1

In software provided for multiple system on a chip microcontrollers I discovered this piece of code

String getMacAddress() {
  uint8_t baseMac[6];
  char baseMacChr[13] = {0};
#  if defined(ESP8266)
  WiFi.macAddress(baseMac);
  sprintf(baseMacChr, "%02X%02X%02X%02X%02X%02X", baseMac[0], baseMac[1], baseMac[2], baseMac[3], baseMac[4], baseMac[5]);
#  elif defined(ESP32)
  esp_read_mac(baseMac, ESP_MAC_WIFI_STA);
  sprintf(baseMacChr, "%02X%02X%02X%02X%02X%02X", baseMac[0], baseMac[1], baseMac[2], baseMac[3], baseMac[4], baseMac[5]);
#  else
  sprintf(baseMacChr, "%02X%02X%02X%02X%02X%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
#  endif
  return String(baseMacChr);
}

Where String is provided by Arduino context. So on those microcontroller is this piece of code safe?

I know that there is a problem with the scope/longevity of the returned variable (well explained here: Returning a C string from a function ) which most people get around with the std::string but I don't have any experience in the context of microcontrollers, and since I've seen it used a lot, I've come up with this question.

I haven't found any documentation about it, every bit of extra information is welcome.

gre_gor
  • 6,669
  • 9
  • 47
  • 52
Odyno
  • 51
  • 6

3 Answers3

4

Is it safe returning Arduino String

Yes. String manages it's memory.

from a C function?

Well, it's not a "C function", it's a normal function in C++.

which most people get around with the std::string but I don't have any experience in the context of microcontrollers

It does not differ that much, and you can also use std::string on esp.

String and other similar interfaces from Arduino are there to save memory (use realloc, instead of delete+new on resize) and to interface with Arduino specific stuff easier (constructor with __FlashStringHelper). It's meant to "mimic" std::string with some Arduino or embedded specific behavior.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111
3

The String class in arduino does not store a pointer to a character but copies it into its internal memory.

The copy constructor takes care of the rest when returning String from a function.

So yes, it's safe

Serve Laurijssen
  • 9,266
  • 5
  • 45
  • 98
2

Looks fine to me since you are allocating the strings with automatic storage duration in the caller to the function.

Check they are of sufficient size though - you need to consult the function documentation for that.

With return String(baseMacChr);, baseMacChr does not go out of scope conceptually until the closing } of the function getMacAddress, so that too is safe.

If you can use std::string rather than String then it would be even better. Every C++ programmer knows exactly what the former is. Using String (whatever that is) can only add to confusion.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483