Печатная продукция отличается при печати переменных функции - PullRequest
0 голосов
/ 14 октября 2019

Я попытался решить упражнение, в котором мы должны вернуть структуру, содержащую первое слово, разделенное пробелами, и его длину в заданной строке. Пример: «Тестовая строка» возвращает {«Тест», 4}.

Чтобы решить эту проблему, я реализовал следующую функцию:

struct string whitespace(char* s){
    char* t = s;
    size_t len = 0;
    while(*t != ' '){
        len++;
        t++;
    }
    char out[len+1];
    strncpy(out, s, len);
    if(len>0){
        out[len] = '\0';
    }
    //printf("%d\n",len);
    struct string x = {out, len};
    return x;
}

со структурой, определенной следующим образом:

struct string{
    char* str;
    size_t len;
};

Если я запускаю следующую основную функцию:

int main(){
    char* s = "Test string";
    struct string x = whitespace(s);
    printf("(%s, %d)\n", x.str, x.len);
    return 0;
}

, я получаю такой вывод:

(, 4)

где, когда я удаляю комментарий //printf("%d\n",len);, я получаю:

4
(Test, 4)

Фактически, строка (Test, 4) выводится всякий раз, когда я распечатываю данную переменную в функции whitespace(char* s). Кроме того, при использовании различных gcc флагов оптимизации, таких как -O3 или -Ofast, результат будет правильным даже без печати переменных в функции.

Я столкнулся с каким-то неопределенным поведением? Может кто-нибудь объяснить, что здесь происходит?

1 Ответ

2 голосов
/ 14 октября 2019

Возвращаемая вами структура включает в себя char *, который вы указываете на локальную переменную out. Эта переменная выходит из области видимости при возврате из функции, поэтому разыменование этого указателя вызывает неопределенное поведение .

Вместо использования VLA, объявите out в качестве указателя и выделите для него памятьуказать на. Затем вы можете безопасно установить член структуры на этот адрес, и память будет работать на протяжении всей программы.

char *out = malloc(len+1);

Кроме того, обязательно free эта память перед выходом из программы.

...