2

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,115
  • 9
  • 39
  • 46
Odyno
  • 61
  • 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
  • 96,430
  • 6
  • 33
  • 74
4

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
  • 8,981
  • 5
  • 35
  • 82
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
  • 227,678
  • 33
  • 352
  • 470