It is all largely irrelevant in terms of memory utilisation and management - when my application is reading or writing out SD card data while serving up a web page total heap memory utilisation runs up to about 2K. Eliminating the use of Strings is not going to eliminate other dynamically created memory objects and buffers used within the SDFat (SD Card) and Ethernet libraries. I might as well use Strings which as dynamically created objects will also use the widely varying in size/utilisation heap memory.
IMO, this is the crux of the debate right here. With all the objects being created and destroyed in largely OOP-based libraries, I don't know why String in particular gets so much hate. It doesn't seem fair to call out one example of dynamic allocation -- well, I got some heat for defending malloc() too, so I guess there are actually a couple. I assume the intent is based on low-hanging fruit, but why aren't there more suggestions to move object initialization into setup() when using files from SD cards, or other short-lived objects for example?
ANY dynamically allocated memory has the potential to fragment memory. If all memory is always allocated, then deallocated, in FILO order, there is no fragmentation, ever. Otherwise, there is fragmentation. If ever during the course of your application's runtime, all dynamically-allocated memory is freed, then you start with a clean slate again. AFAIC, that's the only thing you need to know.
Use String, use char, use malloc(), whatever. If you know you'll be creating strings (any) dynamically, and their lifetimes will vary, it might be better to create a pool of adequately-sized char arrays and assign them as needed. OTOH, if you call a function, create a string, use the string, then it falls out of scope when you exit that function, then it doesn't much matter what you use. Unless, of course, you also have memory allocation happening via an interrupt.
Finally, no one cares where in memory blocks are allocated, that's not relevant. (Usually. I'm sure someone will provide an example otherwise.) The only thing that matters is the order in which they and all following blocks are allocated, and then deallocated. Nevermind, that's just asking for it. :) Heap vs. stack springs to mind immediately.