0
votes

So, I am getting a seg fault whenever I try to call strtok_r, however I am not completely sure why. I am getting this error within this block of code.

I know my error is coming from this section of code, because if I were to take out this while loop, and replace with simply just a printf(str); I get no errors and it prints correctly.

Below is my method containing strtok_r:

void parseCommand(char *str)
{
  char *curr;
  char *temp = str;
  char **args=NULL;

  int i = 0;
  curr=strtok_r(temp, " ", &temp);
  while(curr!=NULL){
    args[i]=curr;
    curr=strtok_r(NULL," ",&temp);
    i++;
  }

  for(int j = 0;j<i-1;j++){
    printf("%s", args[j]);
  }
}

If my understanding of seg faults are correct, this is happening because I am trying to access some sort of memory that this process doesn't have permission to access, but I am unsure why. Anything helps!

EDIT: I have tried to experiment with this a little bit, and had assumed that there wasn't a null terminator at the end of my string, however when I added the line

strncat(cur,"\0",50);

to the inside of my while loop, just before I assign to args[i] the same result is yielded.

EDIT: updated strtok_r usage

1
char **args=NULL ... args[i]=curr;. You never allocated any space for args.Christian Gibbons
How would I know how much space to allocate, if my input can be of variable length?backward forward
If the input string has length N, there can be at most N/2 tokens.user3386109
@backwardforward Any way that you want. There are lots of options. You can guess and re-allocate more if needed. You can allocate more than you will ever need and "right size" afterwards. There are lots of other ways too.David Schwartz
Also notice that you call strtok_r incorrectly. Only the first call shall pass temp. All following calls shall pass NULL4386427

1 Answers

1
votes

I see two problems:

  1. No memory assigned to args

  2. Wrong use of strtok_r

To solve the first problem you can use realloc when new tokens are found.

To solve the second problem, you need to call strtok_r once using str and then NULL the rest of the time.

Something like:

void parseCommand(char *str)
{
  char *curr;
  char **args=NULL;
  char *saveptr;  

  int i = 0;

  // Look for first token, i.e. pass str
  curr = strtok_r(str, " ", &saveptr);
  
  while(curr != NULL){
    // Allocate memory for the pointer
    char **p = realloc(args, (i + 1) * sizeof *p);
    if (p == NULL) exit(1);
    args = p;

    // Save the pointer
    args[i]=curr;
    i++;

    // Look for next token, i.e. pass NULL
    curr = strtok_r(NULL, " ", &saveptr);
  }

  for(int j = 0; j < i; j++){
    printf("%s\n", args[j]);
  }
}

When you call the function do:

char some_text[] = "Hello how are you";
parseCommand(some_text);

Do not call like

parseCommand("Hello how are you");  // Illegal

strtok_r will modify the passed string so you must pass it a string that can be modified.