Вопрос по return, compiler-warnings, pointers, c – C Возвращает символ [] Предупреждение «возвращает адрес локальной переменной» [дубликат]

5

На этот вопрос уже есть ответ здесь:

Возвращение адреса поведения локальной переменной [дубликат] 2 ответа

Это часть домашнего задания.

Я пытаюсь прочитать и вернуть одну строку файла в моем методе getLine.

char *getLine(FILE *input) {
    char line[30];
    if(fgets(line, sizeof(line), input)!=NULL)
    {
        return line;
    }else{
        return NULL;
    }
}

Казалось бы, это работает из того, что меня учили относительно указателей, однако я не могу удалить предупреждающее сообщениеwarning: function returns address of local variable [enabled by default], Это предупреждение относится к строкеreturn line;, Мое задание требует, чтобы у меня не было предупреждений или ошибок при компиляции. Я не вижу, что я делаю неправильно.

Большая часть помощи, которую я нашел, предполагала наличие места для строки текста, но мы еще не рассмотрели это в классе, хотя я сделал это в другом классе. Это действительно лучший способ сделать это? Если да, смогу ли я бесплатно где-нибудь в программе?

Это довольно распространенная ошибка, поэтому вы обязательно найдете десятки сообщений о том, как столкнуться с этой проблемой :) Одна из причин этого заключается в том, что большинство компиляторов даже не предупреждают вас о том, что вы делаете:ideone.com/S5Se71 LihO
использованиеmalloc если вы хотите выделить память на кучу. И этот вопрос уже задавался здесь бесчисленное количество раз. KBart
Локальная переменная перестает существовать, когда функция возвращается, тогда вы возвращаете висячий указатель. Позвольте мне найти дурака. Daniel Fischer
Таким образом, этот вопрос является дубликатом дубликата? Какая? Braden Best
Что подразумевает, что вы должны точно знать, что вы делаете :) LihO

Ваш Ответ

2   ответа
14

char line[30]; массив с автоматической продолжительностью хранения Память, в которой она находится, освобождается после того, как выполнение выходит за пределы вашей функции, поэтому указатель на эту память, которую вы возвращаете, становится недействительным (висячий указатель).

Попытка получить доступ к памяти, которая уже была освобождена, приводит кнеопределенное поведение.

Вы можете выделить свой массив динамически и позволить вызывающей стороне явно освободить его:

char *getLine() {
    char* line = malloc(30);
    ...
    return line;
}

// somewhere:
char* line = getLine();
...
free(line);
Я должен сделать шаблон этого ответа ..;) KBart
5

не охватывается более ранними вопросами, насколько я мог найти:

/* Warning, this function is not re-entrant. It overwrites result of previous call */
char *getLine(FILE *input) {
    static char line[30];
    return fgets(line, sizeof(line), input);
    /* fgets returns NULL on failure, line on success, no need to test it */
}

Объяснение:статические переменные всфера действия сохранить их значения даже после возврата функции. Существует только один экземпляр такой переменной, один и тот же используется при каждом вызове этой функции (поэтому не является повторно входящим / поточно-безопасным). Память для статических переменных выделяется при запуске программы, это не куча и не стек, а отдельная зарезервированная область в области памяти запущенной программы. Значение статической переменной инициализируется только один раз, до того, как оно будет впервые использовано (выше не имеет конкретной инициализации, поэтому оно заполняется 0, но может также иметь инициализатор, и это будет только его значением, когда функция вызывается в первый раз).

Хотя использование статической переменной таким образом может показаться немного странным (и я согласен, что так и есть), это все еще допустимый шаблон, также используемый в стандартном C, напримерс участиемstrtok() функция, Это также демонстрирует необходимость версии, которая является вновь поступающей, так как стандарт C также имеетstrtok_r(), который более сложен в использовании, так как содержит один дополнительный параметр вместо локальной статической переменной.

Похожие вопросы