I am building a command line parser in C, where I take a command line input and organize it into a struct pipeline
. The struct has a commands
member that contains a struct that has the first command, its arguments, and a pointer member that points to the next command struct, and so on and so forth. The commands and the corresponding arguments are seperated by a pipe in the input string. Each command struct has a member char*
array called command_args
that holds the command and all the arguments.
My function seems to work correctly in most cases, but in some weird instances, the commands will be replaced with a seemingly random string. I noticed it seems to not occur with the first command, and only occurs when there are more than one arguments. Using a debugger, I noticed that at first, the command is inserted into the struct correctly, but later when the function gets to the second argument, the argument is inserted into the struct place correctly, but simultaneously replaces the command with a different value. I noticed it seems to never occur with the first command (only the subsequent ones), and only occurs when there are more than one arguments.
The seemingly random string being assigned is "\320" or "\240" or something along those lines
Your code has undefined behavior because you attempt to malloc a block of memory that is too small. As a result, you write into memory that you don't have access to, and anything can happen.
Let's look at this part of code.
if(command_line[i] == '|')
{
argCount = 0;
struct pipeline_command* nextc;
nextc = malloc(sizeof(struct pipeline));
current->next = nextc;
current = nextc;
}
You malloc
a memory of the size of struct pipeline
, but your pointer is of type struct pipeline_command*
. For example on x86_64 with gcc, sizeof(struct pipeline)
is 16, while sizeof(struct pipeline_command)
is 2080, and offsetof(struct pipeline_command, next)
is 2072, so you are already accessing invalid memory right in the next line.
To avoid this type of error, you can directly use sizeof
operator with an expression rather than a type.
Change
nextc = malloc(sizeof(struct pipeline));
to
nextc = malloc(sizeof *nextc);