Your base assumption is that there is something the authors of the String class could/should have done to avoid memory fragmentation. There is not.
Well, there was one thing. Instead of allocating memory again for every single character being added, most String classes allocate more memory is somewhat larger chunks. Allocating memory to hold the current data plus 10 characters, when the previous allocation was filled, would reduce the number of times malloc(), memcpy(), and free() need to be used.
The tradeoff is that the number of unused elements at the end needs to be managed, but that is not a big deal.
This is not to say that I think the String class is a good idea. I do not. But, there are things that it could do better.