2

I have made a program that breaks a string into tokens separated by space and then copies each separate string into an array of strings.

Program works fine until it reaches for-loop and after successfully adding the first string into the array and printing it, program crashes. I debugged it and found that

args[i] = malloc((strlen(comm_str) + 1) * sizeof(char));

returns SEGFAULT then performing loop for the second time. Also call stack prints out the following:

Address: 75F943F9, Function: strlen(), File: C:\Windows\syswow64\msvcrt.dll.`

I tried to correct program myself, but with no result. I thought at first that loop tries to access out of bound region, but I think I have malloc'd everything correctly.

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

int main(){

    char **args = NULL;
    char input[] = "cmdline -s 20 -r -t parameter -p 20 filename";

    int num = 0;
    char *comm_str = strtok(input, " ");                            /*Tokens command line*/

    while(comm_str != NULL){                                        /*Counts number of tokens*/
        num++;
        printf("%s %d\n", comm_str, strlen(comm_str));
        comm_str = strtok(NULL, " ");
    }
    printf("\n");

    args = malloc(num * sizeof(char*));                          /*Allocates memory for the first string entry*/
    if(!args){
        return 0;
    }

    comm_str = strtok(input, " ");                                  /*Starts tokening from beginning*/
    for(int i = 0; i < num; i++){
        args[i] = malloc((strlen(comm_str) + 1) * sizeof(char));    /*Allocates memory for strings*/
        if(!args[i]){
            for(int b = 0; b < i; b++){
                free(args[b]);
            }
            free(args);
            return 0;
        }
        strcpy(args[i], comm_str);
        printf("%s\n", args[i]);
        comm_str = strtok(NULL, " ");
    }

    printf("%d\n", num);

}
6
  • "returns SEGFAULT then [...]" - come again? Commented Mar 6, 2014 at 21:40
  • You might be forgetting to allocate memory properly. args[0...num-1] should be malloc'd too. "returns SEGFAULT then..." does not sound right. Commented Mar 6, 2014 at 21:44
  • I think then is a typo for when Commented Mar 6, 2014 at 21:44
  • @vpit3833 he's getting the segfault while he's mallocing them. Commented Mar 6, 2014 at 21:44
  • No, then i=0, loop performs without problem and prints out "cmdline", but after that (i=1) at 'args[i] = malloc((strlen(comm_str) + 1) * sizeof(char));' SEGFAULT happens. Commented Mar 6, 2014 at 21:45

4 Answers 4

4

strtok is, as you know, altering the string.

After calculating the number of words, the string will contain a single word. Hence the next strtok will return NULL.

Calculate the number of arguments in a non-destructive way, or make a copy of the string.

Sign up to request clarification or add additional context in comments.

1 Comment

Got it! Didn't know that strtok alters the original string, but now I have made the second copy of it and for loop works as intended. Thank you for help.
1

According to the man pages for strtok: "Be cautious when using these functions. If you do use them, note that: These functions modify their first argument. These functions cannot be used on constant strings."

So, the first time you parse to find num, you modify your input string, and as such the second time you parse garbage, which causes the SEGFAULT. Also, you shouldn't use the constant string :

char input[] = "cmdline -s 20 -r -t parameter -p 20 filename";

Comments

0

The first problem is that you have not included the relevant function prototypes. This will make it assume everything is an integer. See below:

$ gcc -Wall x.c -o x
x.c: In function ‘main’:
x.c:9:5: warning: implicit declaration of function ‘strtok’ [-Wimplicit-function-declaration]
x.c:9:22: warning: initialization makes pointer from integer without a cast [enabled by default]
x.c:13:9: warning: implicit declaration of function ‘strlen’ [-Wimplicit-function-declaration]
x.c:13:37: warning: incompatible implicit declaration of built-in function ‘strlen’ [enabled by default]
x.c:13:9: warning: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘long unsigned int’ [-Wformat]
x.c:14:18: warning: assignment makes pointer from integer without a cast [enabled by default]
x.c:18:5: warning: implicit declaration of function ‘malloc’ [-Wimplicit-function-declaration]
x.c:18:12: warning: incompatible implicit declaration of built-in function ‘malloc’ [enabled by default]
x.c:23:14: warning: assignment makes pointer from integer without a cast [enabled by default]
x.c:24:5: error: ‘for’ loop initial declarations are only allowed in C99 mode
x.c:24:5: note: use option -std=c99 or -std=gnu99 to compile your code
x.c:25:27: warning: incompatible implicit declaration of built-in function ‘strlen’ [enabled by default]
x.c:27:13: error: ‘for’ loop initial declarations are only allowed in C99 mode
x.c:28:17: warning: implicit declaration of function ‘free’ [-Wimplicit-function-declaration]
x.c:28:17: warning: incompatible implicit declaration of built-in function ‘free’ [enabled by default]
x.c:30:13: warning: incompatible implicit declaration of built-in function ‘free’ [enabled by default]
x.c:33:9: warning: implicit declaration of function ‘strcpy’ [-Wimplicit-function-declaration]
x.c:33:9: warning: incompatible implicit declaration of built-in function ‘strcpy’ [enabled by default]
x.c:35:18: warning: assignment makes pointer from integer without a cast [enabled by default]
x.c:40:1: warning: control reaches end of non-void function [-Wreturn-type]

I suggest you fix that before proceeding.

1 Comment

I have included #include <string.h>, #include <stdlib.h> and #include <stdio.h> and my compiler returns no warnings.
0

strtok replaces each ' ' with a NULL in your case. Consider the following:

char input[] = "cmdline -s 20 -r -t parameter -p 20 filename";
size_t inputSize = strlen(input);

for(int i = 0; i < inputSize; i++)
    printf("%02X ", input[i]);
printf("\n\n");

char *comm_str = strtok(input, " "); 
while(comm_str != NULL)
    comm_str = strtok(NULL, " ");

for(int i = 0; i < inputSize; i++)
    printf("%02X ", input[i]);
printf("\n\n");

Output:

63 6D 64 6C 69 6E 65 20 2D 73 20 32 30 20 2D 72 20 2D 74 20 70 61 72 61 6D 65 74 65 72 20 2D 70 20 32 30 20 66 69 6C 65 6E 61 6D 65 

63 6D 64 6C 69 6E 65 00 2D 73 00 32 30 00 2D 72 00 2D 74 00 70 61 72 61 6D 65 74 65 72 00 2D 70 00 32 30 00 66 69 6C 65 6E 61 6D 65

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.