Может ли / Почему использование char * вместо const char * в возвращаемом типе вызывать сбои?
Вопрос
Я где-то читал, что если вы хотите, чтобы функция C / C ++ возвращала массив символов (в отличие от std::string), вы должны возвращать const char*, а не char* .Выполнение последнего может привести к аварийному завершению работы программы.
Кто-нибудь смог бы объяснить, правда это или нет?Если это правда, то почему возврат символа * из функции так опасен?Спасибо.
const char * my_function()
{
....
}
void main(void)
{
char x[] = my_function();
}
Решение
Если у вас есть функция, которая возвращает "строковые литералы", то она должна возвращать const char*.Их не нужно выделять в куче с помощью malloc, поскольку они компилируются в раздел самого исполняемого файла, доступный только для чтения.
Пример:
const char* errstr(int err)
{
switch(err) {
case 1: return "error 1";
case 2: return "error 2";
case 3: return "error 3";
case 255: return "error 255 to make this sparse so people don't ask me why I didn't use an array of const char*";
default: return "unknown error";
}
}
Другие советы
Вам сказали, что не верно.
Возвращение const char *
может улучшить семантику функции (т.е. не связываться с тем, что я вам даю), но возвращение char *
совершенно хорошо. р>
Однако в любом случае вы должны убедиться, что вы возвращаете char *
или const char *
который был размещен в куче в my_function
(т.е. выделен с использованием malloc
или new
), в противном случае всякий раз, когда my_function
возвращает память для [const] char *
будет освобождена, и вы получите доступ к неверному указателю.
И, наконец, вы должны не забыть бесплатно
или удалить
[const] char *
, который будет возвращен вам, как только вы закончите с ним, или вы потеряете память. Разве C / C ++ не такие замечательные языки?
Итак, в C у вас будет
const char *my_function() {
const char *my_str = (const char *)malloc(MY_STR_LEN + 1); // +1 for null terminator.
/* ... */
return my_str;
}
int main() {
const char *my_str = my_function();
/* ... */
free(my_str);
/* ... */
return 0;
}
Обычно это не проблема, но есть вещи, которые следует учитывать.Обычно это вопрос постоянной корректности, что означает отслеживание того, что вы можете изменить, а что нет.
Если вы возвращаете строку, заключенную в двойные кавычки, это const char *
, и относиться к этому как к чему-либо другому - это приглашение к неприятностям.Изменение такой строки является неопределенным поведением, но обычно приводит к аварийному завершению работы программы или изменению этой строки, где бы на нее ни ссылались.
Если вы вернете массив символов в стек (т. Е. локальную переменную вызываемой функции), он исчезнет, и указатель не будет указывать ни на что конкретное, возможно, с плохими результатами в какой-то момент.
Если вызываемая функция возвращает что-то, что уже const char *
, затем меняя его на char *
требуется актерский состав.Кроме того, если вы действительно собираетесь его изменить, вы должны быть уверены, что его можно изменить.Обычно гораздо лучше оставить это как есть. const char *
.
Нет никаких непосредственных проблем с возвратом памяти, выделенной с помощью malloc()
или new
, но у вас действительно есть проблема собственности:какая функция должна free()
/delete
это, когда и что вы делаете с возможными копиями?Вот где блистают умные указатели C ++.
Если символ * размещен в стеке, вы возвращаете висячий указатель. В противном случае, если оно соответствует прототипу функции, а объявление соответствует возвращаемому значению, все будет в порядке.
Простое изменение кода возврата не приведет к сбою. Однако, если возвращаемая вами строка является статической (например, return " AString "
), вы должны вернуть const char *
, чтобы убедиться, что компилятор обнаруживает любые попытки его модификации. памяти, которая может вызвать сбой. Конечно, вы можете использовать приведения и тому подобное, чтобы обойти проверки компилятора, но в этом случае вам придется работать , чтобы произошел сбой.