std::string sam sobie alokuje pamięć, to prawda, ale musi wiedzieć, że ma sobie zaalokować. Ty po prostu tworzysz pustego stringa i próbujesz coś pisać do jego wewnętrznego bufora. I tutaj dwie poważne uwagi:
- skoro string jest pusty, to można być niemal pewnym, że c_str() da ci nullptr a nawet jeśli nie, to nie masz żadnej informacji o ilości tej pamięci
- nie po to c_str zwraca const char*, żebyś to sobie castował na non-const i do tego pisał
Modyfikując twoją metodę, tak żeby było poprawnie:
zarezerwuj sobie na stosie pamięć w której na pewno zmieści się się reprezentacja "stringowa" liczby i dopiero z tego twórz stringa. Np.:
char buf[1024];
sprintf(buf, "%llu", i);
string tmp = buf;
Jak najlepiej? Skorzystać z std::to_string i mieć spokój