I seem to have a memory leak which causes the processor to crash.
Using ESP8266 (NodeMCU) board.
I've cut my code down to bare minimum to demonstrate the issue.
Application prints out loop count and free heap size.
Starts with: "LoopCount: 1, FreeHeap: 47152"
Ends with: "LoopCount: 255, FreeHeap: 416"
I'm not familiar with the library, but I don't see anything immediately jumping out of your code that looks like it could cause the memory leak. The fault may well be in the library itself. You need to experiment a bit more to narrow down the trigger, eg.
make WiFiClient client; a global, see if the behaviour changes
remove the client.stop() and let client.connect() implicitly disconnnect
try without the readStringUntil()
...
And then have a look in the library source code for possible candidate leaks.
I know String is frowned upon in the forum here, but if it is so bad that it causes problems even in this small piece of code, then it is basically useless.
Anyway, if that could be the cause of the problem, then the OP will need to swap readStringUntil() for size_t readBytesUntil(char terminator, char *buffer, size_t length)
Which, in my case may be fine because I'm not actually sending anything to the server, so will not be getting anything back. Just connecting / disconnecting for this debug code.
is incorrect YOU are required to delete and do mean use delete the String returned by .readStringUntil().
Of course use of blocking functions is stupid!
Mark
readStringUntil() returns a String object on the stack, and it also appears to offer some sort of time-out mechanism (probably 5 seconds in this case):
String Stream::readStringUntil(char terminator) {
String ret;
int c = timedRead();
while(c >= 0 && c != terminator) {
ret += (char) c;
c = timedRead();
}
return ret;
}
holmes4:
IT CANNOT RETURN ANYTHING ON THE STACK! Look up how the stack works!
Mark
OK. A search for "how a stack works" returned this page as the first hit.
As you can see, by placing the arguments on the stack, the stack frame for main() has increased in size. We also reserved some space for the return value. The return value is computed by foo(), so it will be filled out once foo() is done.
is incorrect YOU are required to delete and do mean use delete the String returned by .readStringUntil().
Your advice is incorrect. There are hidden ways that this local variable is assigned a return value from the call. You should not delete POSTrLine, because it is a local variable (on the stack), not something created with new (from the heap).
holmes4:
IT CANNOT RETURN ANYTHING ON THE STACK! Look up how the stack works!
Objects can be returned from functions. They are on the stack. I think you need to look up how C++ manages this for you. Try this and this.
holmes4:
Of course use of blocking functions is stupid!
+1
arduarn:
then [String] is basically useless.
+1
The OP's problem is probably caused by the combination of:
Unbounded heap usage by String (i.e., no limits on String length)
Limited RAM due to large libraries (increases likelihood of stack and heap colliding)
Rapidly constructing/destructing and connecting/disconnecting the WiFiClient (thrashing network activities)
Rapidly constructing/destructing and connecting/disconnecting the WiFiClient (thrashing network activities)
Adding a delay(100), or delay(5000) at the end of the loop{} doesn't change the result. FreeHeap still keeps going down with every iteration and eventually gets close to zero -> crashes.
Making WiFiClient client global by itself does not solve the issue.
Removing client.stop() by itself does not solve the issue.
Making the WiFiClient client global AND removing client.stop() seems to help.
The HeapSize is stable but what happens is that the connection never closes. Not sure if that is acceptable from the server side...
What I've gathered is that client.connect() generates a new instance every time... Not a C++ expert so need to learn / understand the underlying libraries.