Reputation: 101
This piece of code was working fine, until I modified it.
int main(int argc, char** argv)
{
char command[1024];
gets(command);
char *delim = " \t\f";
char **tokens;
int i=0;
/* Extracting tokens from command string */
for(tokens[i] = strtok(command, delim); tokens[i] != NULL; tokens[i] = strtok(NULL, delim))
{
i++;
}
return 0;
}
And here's the code that crashed with a Segmentation Fault on line
for(tokens[i] = strtok(command, delim); tokens[i] != NULL; tokens[i] = strtok(NULL, delim))
Code:
void commandProcess(char command[])
{
char *delim = " \t\f";
char **tokens;
int i=0;
/* Extracting tokens from command string */
for(tokens[i] = strtok(command, delim); tokens[i] != NULL; tokens[i] = strtok(NULL, delim))
{
i++;
}
}
int main(int argc, char** argv)
{
char command[1024];
gets(command);
process(command);
return 0;
}
I know that char command[]
decays to a pointer link, and also that strtok() modifies its first parameter and in my case it might be an undefined behaviour. link
So, could anybody please provide me some other way around, so that I can work out with the same function signature and still avoid the problem?
This seems a trivial problem, but I cannot make through it. :\ I even tried this,
void commandProcess(char command1[])
{
char command[1024];
int length = strlen(command1);
strncat(command, command1, length);
command[length] = '\0';
char *delim = " \t\f";
char **tokens;
int i=0;
/* Extracting tokens from command string */
for(tokens[i] = strtok(temp_command, delim); tokens[i] != NULL; tokens[i] = strtok(NULL, delim))
{
i++;
}
but then again crashes on the line
for(tokens[i] = strtok(temp_command, delim); tokens[i] != NULL; tokens[i] = strtok(NULL, delim))
I think that delim
& tokens
are not the culprits because the program without commandProcess() worked fine with them.
Upvotes: 1
Views: 591
Reputation: 48033
As other comments and answers have pointed out, you need to allocate space for the token pointers you collect.
Here's a fixed version, which also uses fgets()
instead of the obsolete and dangerous gets()
. Normally, unfortunately, fgets
is a bit of a nuisance, because it leaves the trailing \n
in the buffer. Here, however, that's trivial to account for, as we can simply add '\n'
to the delim
variable telling strtok
what to split on.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXTOKS 100
void commandProcess(char command[])
{
char *delim = " \t\f\r\n";
char *tokens[MAXTOKS+1];
int i=0;
/* Extracting tokens from command string */
for(tokens[i] = strtok(command, delim); tokens[i] != NULL; tokens[i] = strtok(NULL, delim))
{
i++;
if(i > MAXTOKS)
{
fprintf(stderr, "too many tokens\n");
exit(1);
}
}
for(i = 0; tokens[i] != NULL; i++) printf("%d: \"%s\"\n", i, tokens[i]);
}
int main(int argc, char** argv)
{
char command[1024];
fgets(command, sizeof(command), stdin);
commandProcess(command);
return 0;
}
Upvotes: 1
Reputation: 225007
You write to tokens[i]
, but tokens
is never initialized. Dereferencing an uninitialized pointer invokes undefined behavior.
This means the behavior of the code is unpredictable. It may crash, it may show strange results, or it may appear to work correctly. Also, making a seemingly unrelated code change can change how undefined behavior manifests. This is what happened in your case.
To fix this, you need to allocate space to tokens
. In this case, the simplest thing to do is make a fixed size array of pointers:
char *tokens[1024];
You can also malloc
the memory so you don't have a large array on the stack:
char **tokens = malloc(sizeof(char *) * 1024);
Since command
is of length 1024, the number of tokens shouldn't be any larger.
Upvotes: 1