realloc () не работает при передаче указателя на char *. Почему? (Потому что это было по стоимости, а не по ссылке!)

ИЗМЕНИТЬ Спасибо, Иоахим. Использовал сигнатуру функции, как вы указали, и передал адрес моих строк. Внутри функции я выполнил realloc (), используя * currBuffer, и поместил значения в строку, используя (* currBuffer) [lenBuffer] ... . :)

Передача значения указателя по значению работала нормально, пока realloc () не решил, что необходимо назначить другое пространство памяти. Должно быть, я только проверил адрес указателя при входе в функцию и не заметил, что он изменился позже.
.......................... ...............................

Моя программа получает ввод пользователя со стандартного ввода, а затем анализирует его на токены. Читая каждый введенный символ, я вызываю addChrToLine(userInput, charCount-1, (char) inputChr); в void addChrToLine (char *currBuffer, int lenBuffer, char inputChr), где добавляю новый символ в строку. Позже, когда я анализирую ввод, я использую ту же функцию addChrToLine при построении проанализированной строки. Однако, когда парсер вызывает функцию, он выдает ошибку на 25-м символе.

Мой код для чтения пользовательского ввода:

    char * userInput = malloc(sizeof(char));
    int charCount = 0;

LOOP
    if (!(inputChr == LF)) { // ignore the LF character as it denotes end of input line
        charCount++;
        addChrToLine(userInput, charCount-1, (char) inputChr);
        continue;
    }

Мой код для добавления символа в текущую строку:

void addChrToLine (char *currBuffer, int lenBuffer, char inputChr) {

    currBuffer = realloc(currBuffer, sizeof(char) * (lenBuffer +2));
    if (currBuffer == NULL) {
        perror(NULL);
        exit(ENOMEM);
    }
    currBuffer[lenBuffer] = (char) inputChr;
    currBuffer[lenBuffer+1] = (char) '\0';
}

Мой код, в котором я разбираю ввод:

    char * parsedCmd = malloc(sizeof(char));
    int ndxOutput = 0;

Switch statement inside a loop to handle variety of cases
    char currChr = command[ndxInput];

    if (addChr) {
        ndxOutput++;
        addChrToLine2(parsedCmd,ndxOutput-1,currChr);
//      parsedCmd = realloc(parsedCmd, sizeof(char) * (ndxOutput+2));
//      parsedCmd[ndxOutput] = command[ndxInput];
//      parsedCmd[ndxOutput+1] = '\0';
        addChr = FALSE;
    }

Для input = алфавит, например, «abcde ... yz», строка пользовательского ввода читается правильно, и при входе на этап синтаксического анализа все соответствует ожиданиям.

При синтаксическом разборе от «a» до «w» указатель char * parsedCmd правильно показывает содержимое. Когда я передаю "x" addChrToLine, он правильно размещает символ и регулирует положение нуля. НО при возврате к следующей строке синтаксического анализатора parsedCmd показывает пустую строку.

Расположение указателя в памяти во время addChrToLine и после вызова такое же, как и раньше (так что realloc () не переместил мои данные). Однако, когда я смотрю в память, первые 8 символов строки теперь равны 0x00, а строка не повреждена включительно после «i», вплоть до «w» (без «x»). Когда код пытается добавить "y" к parsedCmd, оператор realloc () выдает ошибку double free or corruption (fasttop): 0x0000000000605160 ***

Я немного озадачен, почему это происходит.

И что меня еще больше озадачивает, так это то, что если я закомментирую вызов addChrToLine и раскомментирую следующие три строки (которые делают то же самое), ошибки не будет, и синтаксический анализатор завершит свою работу нормально.

Ясно, что я что-то не так делаю с указателями или выделением памяти, но не вижу, что не так.

Может кто-нибудь помочь мне понять, что здесь происходит?


person gone    schedule 13.04.2014    source источник
comment
Почему так много забросов ?? Ну почему?   -  person pmg    schedule 13.04.2014
comment
Они вызывают проблему?   -  person gone    schedule 14.04.2014
comment
Броски просто не нужны. Вы, например, преобразуете переменные типа char в тип char, чтобы их можно было сохранить в массиве char.   -  person Some programmer dude    schedule 14.04.2014
comment
Я знаю. Я изучаю C и использую их, чтобы быстрее усвоить мнемонику. И я не хотел редактировать то, что вставил. Я даже подумывал сделать комментарий по этому поводу, потому что знал, что это привлечет людей, которые сорвут реальную цель вопроса. Но я предпочел не звучать агрессивно и просто копировать то, что получилось.   -  person gone    schedule 14.04.2014


Ответы (1)


Ошибка в том, что C передает аргументы по значению, то есть они копируются. Поэтому, когда вы назначаете currBuffer в функции, вы назначаете (и изменяете) только локальную копию. Когда функция возвращается, старый userInput все еще не изменился.

Чтобы исправить это, вам нужно передать указатель по ссылке, что делается с помощью указателей в C, то есть вам нужно передать указатель на указатель:

void addChrToLine (char **currBuffer, int lenBuffer, char inputChr);

...

addChrToLine(&userInput, charCount-1, (char) inputChr);

Другое решение - вернуть новый указатель:

char *addChrToLine (char *currBuffer, int lenBuffer, char inputChr)
{
    ...
    return currBuffer;
}

...

userInput = addChrToLine(userInput, charCount-1, (char) inputChr);
person Some programmer dude    schedule 13.04.2014