Печать строки, созданной в локальной функции

Я понимаю, что проблема с приведенным ниже кодом заключается в том, что массив символов, в котором хранится ввод, находится в локальной функции. Когда указатель на этот массив символов передается основной функции, этот массив символов должен быть удален из стека.

Однако, когда я пытаюсь напечатать строку, она печатается, несмотря на предупреждения компилятора. Но если я попытаюсь поместить таймер между вызовом функции и оператором печати, строка окажется пустой. Почему это? Является ли «сборка мусора» медленнее, чем оператор печати?

Вывод без сна:

"Строка [строка]"

Выход со сном:

"Строка"

#include <stdio.h>
#include <string.h>
#include <unistd.h>

#define MAX 20

char* get_user_input();
int main (){
    char *choice;
    choice = get_user_input();
    //sleep(1);
    //Add sleep and it won't print
    printf("String: %s\n", choice);

}

char* get_user_input( ) {
    char inbuffer[MAX];
    char *pos;
    printf("Enter string>");
    fgets (inbuffer, MAX, stdin);
    pos = strchr( inbuffer, '\n' );
    if ( pos != NULL ){
        *pos = '\0';
    }
    return inbuffer;
}

person danihodovic    schedule 07.03.2014    source источник
comment
Вероятно, та же память используется для переменных функции сна. Попробуйте другую функцию, чтобы увидеть влияние этой функции.   -  person obareey    schedule 07.03.2014
comment
@GrjeshChauhan Вы действительно должны прочитать вопрос.   -  person Diti    schedule 07.03.2014
comment
В C нет сборки мусора, по крайней мере, по умолчанию. Более вероятно, что вызов sleep перезапишет ваш стек и испортит строку. (Однако это не объясняет, почему printf оставляет его нетронутым.)   -  person M Oehm    schedule 07.03.2014
comment
Почему сон меняет его? Ну, я не знаю, потому что использование возвращаемой переменной приводит к неопределенному поведению. Все может случиться. Если вы знаете, что это неправильно, то не делайте этого... проблема решена.   -  person deviantfan    schedule 07.03.2014
comment
@MOehm Итак, стек должен быть перезаписан, чтобы очистить его в C?   -  person danihodovic    schedule 07.03.2014
comment
Да, память RAM/HDD/... вообще приходится перезаписывать, чтобы поменять. Нет возможности просто сделать его пустым   -  person deviantfan    schedule 07.03.2014
comment
@ Дити, да, я должен, удалить комментарий. (обычно я люблю читать длинные ответы и короткие вопросы :P)   -  person Grijesh Chauhan    schedule 07.03.2014
comment
@deviantfan Что вы подразумеваете под неопределенным поведением?   -  person danihodovic    schedule 07.03.2014
comment
Нет. Последующие вызовы используют то же пространство стека. Пространство не очищается ни при выходе из функции, ни при входе в нее. Вот почему автоматические переменные часто имеют мусорные значения, если вы не инициализируете их должным образом. Я бы не стал слишком углубляться в это, правда. Вы уже выяснили, что нельзя вернуть локальную переменную. Все остальное является домыслами и не заслуживает расследования.   -  person M Oehm    schedule 07.03.2014
comment
@dani-h: Все может случиться, и это (в значительной степени) непредсказуемо. Может быть, он работает, может быть, он дает сбой, может быть, он делает что-то, что вызовет проблемы в будущем (но не сейчас). Или, может быть, он заказывает пиццу...   -  person deviantfan    schedule 07.03.2014
comment
Большинство современных компиляторов выдаст предупреждение, если вы вернете адрес локальной переменной.   -  person Jabberwocky    schedule 07.03.2014


Ответы (1)


В первую очередь это будет связано с перезаписью стека, учтите:

char* get_user_input( ) {
    char inbuffer[MAX];
    char *pos;
    ...
}

void anotherfunc( ) {
    char a[MAX];
    char *b;
}

int main (){
    char *choice;
    choice = get_user_input();
    anotherfunc();
    printf("String: %s\n", choice);
}

Вызов anotherfunc будет использовать ту же стековую память, что и get_user_input(), в этом случае фактически ничего не записывается в a[] или *b, так что ваш *выбор может остаться - просто. Если функция имеет какие-либо локальные переменные, в которые выполняется запись, недопустимый указатель choice будет указывать на то, что там написано.

person TonyWilk    schedule 07.03.2014