@BulldogLowell I am having so much free time in my hand so let me explain one more time why there is a problem because I think you are not the only one not understanding it and also to be 100% I am not the one being wrong.
We call the current dtostrf. What happens is that this function does not know how big the buffer we want him to write in is. It could be any number but dtostrf does not have any clue about it. It could be larger, equal or smaller. If it is larger or equal, we are safe. If it is smaller then that is a bad news. The current dtostrf goes and write the number in the memory not knowing that the buffer is smaller. So the data in memory get corrupted since dtostrf does not stop writing in the memory when the small buffer has been used up.
One might say we know roughly how big our float is so we can make sure we have enough room. That is correct but the problem with float is that it can become very large if you miss few special cases. Let's say you expect your number to be between 0 to 10. Also let's assume you have set the precision (the way it works in current dtostrf) to 1. So the minimum will be "0.0" and the max will be "9.9". So, you want to be as efficient as you can get and you allocate an array with 3 bytes. (I am ignoring the null because dtostrf does not print null as far as I remember). You also set the width to 3.
if the number is 0 you will get [0]- [0] (we are all good)
if the number is 5.3 you will get [5]- [3] (we are all good)
if the number is 9.9 you will get [9]- [9] (we are all good)
Now if you variable for some reasons that you did not predict become something out of the range. let's see what happens:
if the number is -0.1 you will get [-][0]- [1] (We changed some other data byte to '0')
if the number is 10.0 you will get [1][0]- [0] (We changed some other data byte to '0')
or in some very ugly case:
if the number is 10000.0 you will get [1][0][0][0][0]- [0] (We changed some other data bytes to '0' and one byte to '.')
So this is the problem. Now one solution is to put a huge buffer and the problem is that float variable can have a very huge value too. So, you won't be able to find a reasonable size. One way is to check and make sure if the number is in certain range. However the problem is that you should do this every time and on top of that you have to make sure you consider the sign and the precision (precision as it is in current dtostrf). So as you can see not all these solutions are neat.
If we had a dtostrf which would know the size of buffer, everything would be solved. dtostrf is technically aware of everything it is doing. It knows exactly how many bytes are being used and so one, so why not we just tell dtostrf how many byte it can use and then we sleep in peace at night not worrying about the float ending up out of range and screw the whole memory.
One more look at dtostrf
char* dtostrf ( double __val, signed char __width, unsigned char __prec, char * __s)
Conversion is done in the format "[-]d.ddd". The minimum field width of the output string (including the possible '.' and the possible sign for negative values) is given in width, and prec determines the number of digits after the decimal sign. width is signed value, negative for left adjustment.
The dtostrf() function returns the pointer to the converted string s.
in the Arduino implemented:
__prec: determines the number of digits after the decimal point
What would make it safe although not as practical:
__prec: determines the number of digits after the sign
My suggestion for dtostrf:
bool dtostrf (double __val, signed char __width, unsigned char __prec, char * __s, unsigned char __maxSize)
__val: same as current dtostrf
__width: same as current arduino dtostrf
__prec: same as current arduino dtostrf
__s: same as current arduino dtostrf
__maxSize: The number of bytes allocated for this number
return true if the process was successful and maxSize was large enough. Return false if the size was not enough.