Меня всегда смущает возврат строкового литерала или строки из функции.
Неизменяемая буквальная строка
Насколько я понимаю, вы можете безопасно возвращать строковый литерал напрямую, если возвращаемый тип объявлен как const, чтобы объявить, что строка не предназначена для изменения. Это означает, что вам не нужно беспокоиться о сроке службы строки / утечек памяти.
Изменяемая, не-буквальная строка
Однако, если вам нужна строка, которую вы можете изменить на месте, вам нужно учитывать срок жизни строки и размер выделения памяти, в котором она хранится.
Это становится проблемой, поскольку вы больше не можете возвращать одну и ту же память, содержащую строку, для каждого вызова функции, поскольку предыдущее использование могло изменить содержимое этой памяти и / или все еще использоваться. Следовательно, новый фрагмент памяти должен быть выделен для хранения возвращаемой строки.
Это место, где возникает вероятность утечки, и где необходимо сделать выбор относительно того, где должно происходить распределение и перераспределение. Можно было бы, чтобы сама функция выделяла память и указала в документации состояние, в котором это происходит, и указала в нем, что вызывающая сторона должна освободить память, когда она больше не требуется (предотвращая утечку). Это означает, что функция может просто возвращать символ *.
Другой вариант - передать часть памяти функции, которая была выделена вызывающей стороной, и заставить функцию поместить строку в эту память. В этом случае вызывающая сторона одновременно выделяет и отвечает за освобождение этой памяти.
Наконец, я упомянул, что при использовании изменяемой строки необходимо управлять размером памяти и строки. Распределение должно быть достаточно большим для строки, изначально установленной функцией, а также для любых изменений, которые сделаны после функции, до освобождения памяти. Невыполнение этого требования может привести к переполнению буфера, если записать строку, которая будет длинной, чтобы поместиться в первоначально выделенной памяти; это чрезвычайно опасно для здоровья и безопасности вашей программы. Это может вызвать ошибки и дыры в безопасности, которые чрезвычайно трудно обнаружить (поскольку источник ошибки - переполнение - может быть далек от симптомов, наблюдаемых при сбое программы).