Отпечатване на низ, създаден в локална функция

Разбирам, че проблемът с кода по-долу е, че масивът char, където се съхранява входът, е в локална функция. Когато указателят към този char масив бъде предаден на основната функция, този char масив трябва да бъде изтрит от стека.

Въпреки това, когато се опитам да отпечатам низа, той се отпечатва въпреки предупрежденията на компилатора. Но ако се опитам да поставя таймер между извикването на функцията и оператора за печат, низът е празен. Защо е това? „Събирането на боклука“ по-бавно ли е от отчета за печат?

Изход без заспиване:

„Низът е [низ]“

Изход със съня:

"Низът е"

#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
@GrijeshChauhan Наистина трябва да прочетете въпроса.   -  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
@Diti да, трябва да изтрия коментара. (обикновено обичам да чета дълги отговори и кратки въпроси :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