Мне нужно написать небольшую программу на C для университета, которая должна снова печатать заданные параметры в командной строке. Задача сделать это с помощью указателей. Итак, моя проблема в том, что программа работает полностью правильно, когда неиспользуемая переменная bin является частью кода. Но если я попытаюсь удалить код или закомментировать его, программа больше не работает (вылетает или ничего не печатает) ... Но переменная в программе вообще не используется. Также я могу изменить его имя, но не его заявленное значение. Может кто поможет / объяснит, в чем проблема :) Спасибо!

Код:

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

int main (int argc, char *argv[])
{
    char *text;
    char bin = '\0'; //<---- unused variable
    char space = 32;
    int i = 0;

    if(argc == 1){
        printf("Bitte Parameter mit angeben!");
        return 1;
    }

    text = malloc(sizeof(char));

    for(i = 1; i < argc; i++){
        text = realloc(text, sizeof(char) * (strlen(argv[i]) + 2 + 
               strlen(text)));
        if(text == NULL)
            return 1;
        text = strcat(text, argv[i]);
        text = strcat(text, &space);
    }

    text++;
    printf("%s", text);
    free(text);
    return 0;
 }
0
Philipp Hofer 2 Янв 2018 в 22:03

2 ответа

Лучший ответ
text = strcat(text, &space);

Эта строка принимает адрес односимвольной переменной и затем передает его в strcat, который ожидает строковый аргумент с завершающим нулем. Тот факт, что он работает с переменной bin, вероятно, означает, что ваш компилятор решил разместить переменные в стеке рядом друг с другом таким образом, чтобы он рассматривал их как нулевой терминатор; однако, полагаться на это, безусловно, неопределенное поведение.

Было бы лучше предоставить строковый литерал или константу, например:

const char space[] = " ";
...
text = strcat(text, space);

Или просто:

text = strcat(text, " ");

Обратите внимание: хотя это может решить вашу непосредственную проблему, в коде есть и другие проблемы, на которые указали другие. В частности, использование text в strlen перед инициализацией выделенной памяти и освобождение text после перемещения указателя являются неопределенным поведением, и я ожидаю, что вам снова просто повезло, что это работает на данный момент.

1
Zrax 4 Янв 2018 в 21:59

Ваш код присоединяется к text без инициализации text. Вам нужно начать с text как пустой строки:

text = malloc(sizeof(char));
text[0] = `\0` ; // empty string

Тогда передача &space в strcat() будет ошибочной, поскольку space не является строкой с завершающим нулем. Просто замените на:

text = strcat(text, " " ) ;

Затем позже удалите text++, иначе он пропустит первый символ, и вы не сможете free() изменить указатель без ошибки кучи:

// text++;   <<< NOT NEEDED and makes free(text) bound to fail.
printf("%s", text);
free( text ) ;

Почему это сработало с присутствием bin, потому что вам повезло, и он сформировал нулевой терминатор для &space из-за смежности в стеке. Вам снова повезло с тем, на что указывал text без инициализации, и освобождение измененного указателя, возможно, не вызвало ошибки или сбоя, потому что программа завершается без попытки выделить дополнительную память.

3
Clifford 3 Янв 2018 в 10:29