0

EDIT Thanks Joachim. Used the function signature as you pointed out, and passed the address of my strings in. Inside the function, I did the realloc() using *currBuffer, and placed the values into the string using (*currBuffer)[lenBuffer] .... :)

Passing the value of the pointer by-value was working fine until realloc() decided it needed to assign a different memory space. I must have only checked the pointer's address on entry to the function and not noticed that it changed later.
.........................................................

My program gets user input from stdin, and then parses it into tokens. As I read each character entered, I make a call addChrToLine(userInput, charCount-1, (char) inputChr); to void addChrToLine (char *currBuffer, int lenBuffer, char inputChr) where I add the new character to the string. Later, when I'm parsing the input, I using the same addChrToLine function while I build the parsed string. However, when the parser calls the function, it gives an error on the 25th character.

My code to read user input:

    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;
    }

My code to add the char to the current line:

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';
}

My code where I parse the input:

    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;
    }

For input = alphabet, eg "abcde...yz", the user input string is read correctly and everything is as expected on entry to the parsing stage.

While parsing "a" to "w", the char * pointer parsedCmd correctly shows the contents. When I pass "x" to addChrToLine, it correctly places the character and adjusts the position of the null. BUT on return to the parser's next line, parsedCmd shows a null string.

The memory location of the pointer is the same during addChrToLine and after the call as it was before (so realloc() hasn't moved my data). However, when I look at the memory, the first 8 characters of the string are now 0x00 and the the string is intact inclusively after "i", all the way to "w" (no "x"). When the code tries to add "y" to parsedCmd, the realloc() statement issues an error double free or corruption (fasttop): 0x0000000000605160 ***

I'm a bit puzzled why this is happening.

And what puzzles me even more is that if I comment out the call to addChrToLine and uncomment the next three lines (which do the same thing), there is no error and the parser finishes fine.

Clearly I'm doing something wrong with my pointers or memory allocations, but I can't see what's wrong.

Can someone please help me understand what's going on here?

gone
  • 1,079
  • 5
  • 13
  • 31
  • 1
    Why so many casts?? Oh why? – pmg Apr 13 '14 at 18:49
  • Are they causing the problem are they? – gone Apr 14 '14 at 01:51
  • The casts are simply not needed. You are, for example, casting variables of type `char` to type `char` so it can be stored in array of `char`. – Some programmer dude Apr 14 '14 at 06:40
  • I know. I'm learning C and using them to help me learn the mnemonics quicker. And I didn't want to edit what I pasted. I was even thinking of making a comment about it because I knew it would attract people who would derail the real purpose of the question. But I opted not sound aggressive and just cop what came. – gone Apr 14 '14 at 10:11

1 Answers1

2

The error is that C passes arguments by value, meaning they are copied. So when you assign to currBuffer in the function you only assign (and modify) the local copy. When the function returns, the old userInput is still unchanged.

To fix this you have to pass the pointer by reference which is done with pointers in C, that is you have to pass a pointer to the pointer:

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

...

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

Another solution is to return the new pointer:

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

...

userInput = addChrToLine(userInput, charCount-1, (char) inputChr);
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621