Может ли / Почему использование char * вместо const char * в возвращаемом типе вызывать сбои?

StackOverflow https://stackoverflow.com/questions/1421672

  •  07-07-2019
  •  | 
  •  

Вопрос

Я где-то читал, что если вы хотите, чтобы функция 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 * , чтобы убедиться, что компилятор обнаруживает любые попытки его модификации. памяти, которая может вызвать сбой. Конечно, вы можете использовать приведения и тому подобное, чтобы обойти проверки компилятора, но в этом случае вам придется работать , чтобы произошел сбой.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top