Почему операция присваивания меняет присваиваемое значение?

Вот что происходит. Функция stringLoad Принимает строку из потоков ввода (используется malloc для хранения) и делит ее на части, возвращая массив новых строк. Тут начинается проблема, когда я присваиваю указатель первой такой строки в переменную, значение пропадает и из массива, что выдает ошибку.

int main(){
while (1) {
        char** command = stringLoad();
        short counter = 0;
        printf("%s", command[0]);
        char *bufferForCommands;
            bufferForCommands= command[0];
        for (size_t i = 0; i < strlen(command[0]); i++)
        {
            bufferForCommands[i] = tolower(bufferForCommands[i]);
        }
        printf("%s", bufferForCommands);
    }
    return 0;
}

До присваивания После присваивания upd: добавляю функцию stringLoad

char ** stringLoad()
{
    int quantSize = 5;
    char *input;
    input = (char*)malloc(quantSize);
    int restOfSpace = quantSize;
    int locatedMemory = quantSize;
    printf("Введите команду:\n");
    //input[0] = '\0';
    char symbol;
    short cursor = 0;
    while ((symbol = getchar()) != '\n')
    {
        if (restOfSpace == 0) {
            char * newinput = realloc(input, locatedMemory + 5);
            if (newinput != NULL)
                input = newinput;
            else {
                fprintf(stderr, "Memory error\n");
                exit(1);
            }
            locatedMemory += 5;
            restOfSpace += 5;
        }
        input[cursor] = symbol;
        cursor++;
        restOfSpace--;
    }
    if (restOfSpace == 0) {
        char * newinput = realloc(input, locatedMemory + 5);
        if (newinput != NULL)
            input = newinput;
        else {
            fprintf(stderr, "Memory error\n");
            exit(1);
        }
        locatedMemory += 5;
    }
    *(input + cursor) = '/n';
    cursor++;
    input[cursor] = '/0';
    restOfSpace -= 2;

    char* quantedString[10] = { NULL };//Массив строк состоящий из комманд и аргументов
    char* bufferForWriting;
    short counter = 0;
    if ((bufferForWriting = strtok(input, ",/0")) == NULL) {
        quantedString[0] = bufferForWriting;
    }
    else {
        quantedString[0] = input;
    }
    
    while (quantedString[counter] != NULL)// Выделение последующих частей
    {
        counter++;
        bufferForWriting = strtok(NULL, ",");// Выделение очередной части строки
        quantedString[counter] = bufferForWriting;
    }
    free(bufferForWriting);
    return quantedString;
}

Ответы (1 шт):

Автор решения: KoVadim

C - это язык простой. В нем компилятор делает ровно то, что его просят и не стелит соломку для программиста.

Давайте посморим на эту конструкцию

char* bufferForWriting;
//....
// в bufferForWriting  будет указатель на часть строки input, а сама input будет немного модифицированна
if ((bufferForWriting = strtok(input, ",/0")) == NULL) {
    // перепишем указатель (УКАЗАТЕЛЬ!!!) в массив.
    // сами данные продолжают жить в input
    quantedString[0] = bufferForWriting;
}
//...
// а теперь возьмем и почистим память по произвольному указателю
// bufferForWriting ведь теперь показывает где то в середину input.
free(bufferForWriting);

По факту получается, что Вы возвращаете указатель на локальный массив, который внутри содержит указатели на поврежденные участки памяти. Что потом будет с ними - а кто его знает. Пока в отладчике далеко не отошли от вызова, стек ещё не поврежден и Вам удалось наблюдать ожидаемое значение. Как только пошли отладчиком дальше, где объявляются переменные и им что то присваивается, стек был уже другой, но указатели то об этом не знают... и продолжают указывать на память, которая им не принадлежит.

Что делать? Как обычно, тут лучше наверно переписать аккуратно, разделив код на составляющие. Как минимум тут нужно выделить функцию, которая читает пользовательский ввод. Следующим этапом изучить, как работает strtok (а она странная, она модифицирует исходную строку, записывая туда нули на место разделителя, что бы работали строковые функции). А потом ещё изучить не совсем стандартную функцию strdup, которая как раз делает копию строки.

А также описать словами, что именно должна делать эта функция с примерами входных и выходных данных.

→ Ссылка