-
Notifications
You must be signed in to change notification settings - Fork 13.3k
String clear() does not free memory, only set length(0) #8485
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Maybe I am missing some other use case... but what you are describing is destructor of the String object. In case of the container, we remove the element to free the resource. In case that you describe above, operation does make sense though? It discards the original object, replacing it with something completely new. |
Yep, that's exactly my point why it makes no sense this seems to be the only way to actually free the allocated memory. String foo;
String emptyString;
foo.reserve(100);
foo.clear(); // Still allocates the 100 bytes memory
foo = ""; // Still allocates the 100 bytes memory
foo = F(""); // Still allocates the 100 bytes memory
foo = emptyString; // Still allocates the 100 bytes memory
foo = String(); // uses the move copy constructor String::String(String&& other) to free the heap memory. My use case is a buffer object, which keeps log strings. String Message[LOG_STRUCT_MESSAGE_LINES];
unsigned long timeStamp[LOG_STRUCT_MESSAGE_LINES] = {0}; After I sent the log messages to the webserver, I want to free them. |
If these are line entries, have you considered |
Maybe .clear() is still a valid option, instead of And using |
struct Blah : public String {
using String::String;
using String::invalidate;
}; ? In case of the queue I'd still think about actually destroying the String object. |
Yep, so that could be an alternative to overcome the shortcoming of the String object. |
Should not be a problem? We are not introducing any additional code, just add an alias to call the (sort-of internal) method.
No virtual dtor, but it also should not matter in plain inheritance. And note that it also could be solved by having |
Either way, wouldn't it be better if the actual String class has a function to properly free the allocated heap memory? :) |
I think that @TD-er has a point. Right now a Having the |
So just make |
I would not expose |
Not to go in a loop, but |
Fixes esp8266#8485 Whenever the empty C string is assigned or the .clear() method called, free any heap allocated with the String.
I've done some thinking too and maybe the Can you also add a
I think |
Another thing I did realize today, when going through my code. Since String getText() { return F(""); }
String myString;
myString.reserve(100);
myString = F(""); // still allocated 100 bytes
myString = getText(); // No heap allocated anymore Lots of code does something like this: String myString;
myString.reserve(100);
myString = F("MyLog: ");
myString += value;
... But then it really makes a difference when the first assignment is the return String object of a function call or something else like a String object, or whatever you can assign to a String. |
Current API ( String str;
str.reserve(100);
while (some_condition) {
str.clear(); // or str = "";
for (int i = 0; i < N; i++) {
str += 'x';
}
....
} Rather than |
it does not invalidate the pre-reservation.
|
Yep, that's my point. const __FlashStringHelper * myFlash() { return F("MyFlash"); }
String myString() { return F("MyString"); }
String str;
str.reserve(100);
str = myFlash(); // Still 100 bytes allocated;
str += myString(); // Still 100 bytes allocated;
str = myString(); // Work done by reserve is undone. |
I'm in for the best name. std::string does have a Note from that page:
But it also seems to have a So then a |
Just ran into an issue on ESP32 running the latest IDF4.4 Arduino v2.0.2 code String foo, bar;
void myFunction(String&& str) {
foo = std::move(str);
bar = std::move(str);
} N.B. these strings may already contain some data This leads to crashes on ESP32 and not on ESP8266, but will show unintended behavoir (aka: bug) I looked at the code on both ends and the ESP8266: Arduino/cores/esp8266/WString.cpp Lines 238 to 242 in f60defc
IMHO the code on the ESP32 is not really a move, as it also may keep the allocated space in the string and thus probably still keeps the memory allocated when you assign as discussed here as work-around ( TL;DR |
I'm late to the party as it seems, but I want to share my 2 cents as well. I believe assigning "" to a string should NOT release its internal buffer, because then there is no way to reset it's content without going through a complete |
I don’t now why but for me use case (construct web pages) String.clear() does exactly what I need. It clears the string without losing the reserved space. |
Basic Infos
Platform
Problem Description
The String::clear() function does only set the length to 0, it does not free the memory.
The same for assigning an empty string, as this only checks if the reserved capacity is enough.
This means it is quite tricky when clearing a string that's no longer needed.
For example a buffer I'm using, which is an array of String.
The only way to really free the memory is by assigning a new string which will then be copied using the move operator, like this:
It does not really make sense to only set the length of the string to 0, as that's not what
clear()
suggests.Or at least have some function like
free()
to actually free the allocated memory.The text was updated successfully, but these errors were encountered: