954,492 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

Segmentation fault using strtok

I am using strtok to parse the argv. On windows it works just fine but on Solaris I get a fault. I have traced it down to the "$" character on the command line.

char *result = NULL;
    char *value = NULL;
    char *argPointer = NULL;
    char delims[] = " ,=";
    int i = 1;

     while (i < argc)
    {
        argPointer =  argv[i];

        printf("parse the arg %s\n",argPointer);

        result = strtok( argPointer, delims);
          while( result != NULL ) {
                printf( "var is \"%s\"\n", result );
                value = strtok( NULL, delims );
                printf( "value is \"%s\"\n", value );
                        if (strcmp(result,"_VARIABLE") == 0){
                                subjectName = value;
                                printf( "subject is \"%s\"\n", value );
                        }
                        if (strcmp(result,"$TYPE") == 0){
                                printf( "skipping type \n" );
                                break;
                        }
           if (result != NULL && value != NULL){
               status = tibrvMsg_UpdateString(message, result, value);
           }
            result = strtok( NULL, delims );
          }
   i++;
  }
crusty_collins
Newbie Poster
9 posts since Feb 2006
Reputation Points: 10
Solved Threads: 0
 

are the argv[] strings in read-only memory? Maybe you need to copy the string to a temp buffer and use strtok on that temp buffer.

Ancient Dragon
Retired & Loving It
Team Colleague
30,049 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,343
 

>are the argv[] strings in read-only memory?
No, they're required to be writable.

>I have traced it down to the "$" character on the command line.
Can you paste your debug trace here?

Narue
Bad Cop
Administrator
15,460 posts since Sep 2004
Reputation Points: 6,464
Solved Threads: 1,401
 

Also,

What's the command line you are using to run it?

winbatch
Posting Pro in Training
466 posts since Feb 2005
Reputation Points: 68
Solved Threads: 18
 

I am so new to all of this that I am not sure what or how to do a debug trace.. I just inserted printf statments until I found where it failed.
I am using a command line of " _VARIABLE=SRC_SERVICE.IDN.me _HOST=chtsapdbu3 $TYPE=CHI_PRD"

Also I had tried to copy argv to a temp array but had problems.

crusty_collins
Newbie Poster
9 posts since Feb 2006
Reputation Points: 10
Solved Threads: 0
 

What does tibrvMsg_UpdateString do? Is it a library or a function you've written? Also, what are subjectName, status, and message defined as? It would be nice if you could set up the smallest possible test program (that we can compile and run without adding any framework) that exhibits the error and cuts out anything unnecessary.

Narue
Bad Cop
Administrator
15,460 posts since Sep 2004
Reputation Points: 6,464
Solved Threads: 1,401
 

>>Solaris I get a fault. I have traced it down to the "$" character on the command line.

does Solaris shell interpret that $ symbol (is it a special character like '>' and '<')? try putting it in quotes
_VARIABLE=SRC_SERVICE.IDN.me _HOST=chtsapdbu3 "$TYPE=CHI_PRD"

or if that doesn't work, can you escape it?
_VARIABLE=SRC_SERVICE.IDN.me _HOST=chtsapdbu3 \$TYPE=CHI_PRD

Ancient Dragon
Retired & Loving It
Team Colleague
30,049 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,343
 

tibrvMsg_UpdateString is a call to an API.

char* subjectName = NULL;
tibrvMsg message;
tibrv_status status = TIBRV_NOT_INITIALIZED;

I have done some further testing with this and taken out the tibrvMsg_UpdateString to ensure this was not an issue. Still have problems with it dying.

I guess I should look at making a copy of the argv and then using those values?

crusty_collins
Newbie Poster
9 posts since Feb 2006
Reputation Points: 10
Solved Threads: 0
 

I tried to escape it in the loop ( I do not have control of what gets put on argv) I will try and quote it.

crusty_collins
Newbie Poster
9 posts since Feb 2006
Reputation Points: 10
Solved Threads: 0
 

I meant to escepe it on the command-line so that the shell does not interpret it. If you have no control over that, then escaping it is not an option. Doing it after it reaches your program argv[] will do nothing more than put the liberal '\' in argv[] string.

Ancient Dragon
Retired & Loving It
Team Colleague
30,049 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,343
 

I figured that out the hard way. I am thinkinig about doing a regex on each line but am not sure how to do it.
so the argv[i] is string literal? I could create a buffer and then replace "$" with "_"?
Stole this from cplus.com
/* Calculate the length */
length = strlen(argv[1]);
for (i = 2; i < argc; i++) {
length = length + strlen(argv[i]) ;
}
length = length + 1;
/* This last plus one is needed to hold the terminator, '\0' */


/* Allocate the buffer */
buffer = (char *) malloc(length);
if (buffer == NULL) {
printf("Error on malloc");
exit(1);
}

strcpy(buffer,argv[1]);
for (i=1; i< length; i++){
if (strcmp(buffer[i],"$")==0){
buffer[i] = "_";
}
}

crusty_collins
Newbie Poster
9 posts since Feb 2006
Reputation Points: 10
Solved Threads: 0
 

if all you want to do is change the $ to _, you can just change argv[] and not copy to another buffer (see Narue's earlier comment).

for(i = 1; i < argc; i++)
{
    char* p = strchr(argv[i],'$'); // find the $ symbol
    if(p != 0)
        *p = '_';
}
Ancient Dragon
Retired & Loving It
Team Colleague
30,049 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,343
 

Ok guys, first off thank you sooo much for all of the good advice. I have been able to track this down to the strtok having issues with incomplete lines. It was looking for a=b, c=d etc. But I was getting things like $a=b, e= etc. It was a matter of using
the following code for several different scenariosfor(i = 1; i < argc; i++)
{
char* p = strchr(argv[i],'$'); // find the $ symbol
if(p != 0)
*p = '_';
}


So I was able to make some adjustments directly to argv and things have worked out just fine.

crusty_collins
Newbie Poster
9 posts since Feb 2006
Reputation Points: 10
Solved Threads: 0
 

This article has been dead for over three months

Post: Markdown Syntax: Formatting Help
You