delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2013/06/17/05:30:15

X-Authentication-Warning: delorie.com: mail set sender to djgpp-bounces using -f
X-Received: by 10.224.174.145 with SMTP id t17mr7618577qaz.4.1371460683820;
Mon, 17 Jun 2013 02:18:03 -0700 (PDT)
X-Received: by 10.50.36.41 with SMTP id n9mr394152igj.11.1371460683780; Mon,
17 Jun 2013 02:18:03 -0700 (PDT)
Newsgroups: comp.os.msdos.djgpp
Date: Mon, 17 Jun 2013 02:18:03 -0700 (PDT)
Complaints-To: groups-abuse AT google DOT com
Injection-Info: glegroupsg2000goo.googlegroups.com; posting-host=71.222.72.40; posting-account=jrLHRgkAAABPV01ZW_RN_U6Tm5UnYNUx
NNTP-Posting-Host: 71.222.72.40
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <36e857f0-9899-496b-9fc6-32251e109888@googlegroups.com>
Subject: General Protection Fault error is intermittent
From: "K.J.Williams" <lordwilliams1972 AT gmail DOT com>
Injection-Date: Mon, 17 Jun 2013 09:18:03 +0000
Bytes: 11134
Lines: 377
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp
X-MIME-Autoconverted: from quoted-printable to 8bit by delorie.com id r5H9U1ue017760
Reply-To: djgpp AT delorie DOT com

Hi, 

I have a problem with why a General Protection Fault message is not displayed all the time, for a function called string_parser in two different programs. The function called string_parser uses a string.h function called strtok(). I am trying to implement it to work right, and I know that I am not doing it correctly. But the question is why in a smaller program it compiles fine and doesn't exhibit the General Protection Fault message vs. when I implement it in a larger program it does ? 

heres my source code :
/*
  program name: parstext.c
  author: K.J.Williams

  Purpose: This is a sample of how string_parser, which uses strtok() is
           used parse commands in the larger program that I am developing
           called ( by acronym ) WATT.
*/

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

// original design setting:
#define PARSE_SIZE_LIMIT 81

//function prototypes:

short int string_parser(char *, char *, char, short int);//TEXT_PARSER
short int kfgets(char *);//KFGETS
short int ynreturn(void);//yes/no option
short int return_key(void);//waits for user to press ENTER


int main (void)
{
   //declare char arrays and initialize garbage with '\0'

   char target[PARSE_SIZE_LIMIT];//user input
   char worda[PARSE_SIZE_LIMIT]; worda[0] = '\0';//command statement
   char uword[PARSE_SIZE_LIMIT]; uword[0] = '\0';//argument part

   //temporary variables

   short int counta,countb,x,y,z;

   char d;//for first character of a string

   //message

   printf("Compilation Date : %s @ %s PST (24hr format)\n",__DATE__,__TIME__);
   printf("WATT: single text line string parsing tester\n");
   printf("Enter AT Command (ATcmd) statment(s) in the syntax format of\n");
   printf("[#(ATcmd): arg1 arg2 ... argN ] or [#(ATcmd): ] - for no args, and etc.\n");

   //prompt user

    do
    {

    //initialize (or reset) these variables
    z = 1;
    target[0] = '\0';

    //prompt user
    printf("\n>");
    kfgets(target);//use my fgets function

    d = target[0];

    if(d != '#') { return 0; }// if the first character != '#' then exit...


    if( (string_parser(target,worda,'#',-2)) == -1)
    {
      printf("text line uses incorrect syntax with adjacent \'#\' characters\n");
      return 0;
    }

    //otherwise begin parsing....

    counta = string_parser(target,worda,'#',-1);//count tokens & do nothing
    string_parser(target,worda,'#',0);
    printf("[%s]\n..has %d part(s) counted by \'#\'\n\n",worda,counta);

    //parsing each statement and argument by '#', then ' '.

     do
     {
      for(x = 1;x <= z;x++)
      {
         string_parser(target,worda,'#',x);
      }

        printf("part#%d : %s\n",x-1,worda);//-1 for x counter offset

        countb = string_parser(worda,uword,' ',-1);
        string_parser(worda,uword,' ',0);
        printf("[%s]\n..has %d sub-part(s) counted by \' \'\n",uword,countb);

        //if countb == 0 - then do nothing

        if(countb == 1)
        {
          string_parser(worda,uword,' ',1);
          printf("...sub-part#1 : %s\n",uword);
        }

        if(countb > 1)
        {
          for(y = 1;y <= countb;y++)
          {
             string_parser(worda,uword,' ',y);
             printf("...sub-part#%d : %s\n",y,uword);
          }
        }

      //pause
      if(z < counta); { return_key(); }

      z++;

      //end of do..while loop

     }while(z <= counta);

    printf("\ntest again (y/n)?");

    //outer do...while loop
    } while((ynreturn()) == 1);

   return 0;
}

//parses c strings by using single character tokens with strtok();
short int string_parser(char *userstring, char *target, char magic, short int word)
{
  char subject[PARSE_SIZE_LIMIT]; subject[0] = '\0'; //initialize subject

  //w1 = token with null character ; w2 = token without null character
  char w1[2]; w1[0] = magic; w1[1] = '\0';
  char w2[1]; w2[0] = magic;

  //temp variables:
  char a = 0;//copies x before the if evaluation of x - see below
  char b = 0;//copies b after the if evaluation of x - see below
  char c = 0;//the difference between a & b - see below
  char d = 0;//d = subject[x]; - see below

  char x = 0;//for loop counter

  char y = 0;//counts the number of times a magic is in userstring (subject)
             //only if (c > 1)

  char z = 0;//same use as y, but with out the condition of if (c > 1)
             //for use only when word = -2

  short int length;//get the length of the string subject

  char *p;//used for assigning pointer address returned by strtok()

  strcpy(subject,userstring);//copy userstring to subject
  length = strlen(subject);//get length of subject

  //printf("\n");//temp

  //printf("subject = %s\n",subject);//temp
  //printf("word = %d\n",word);//temp
  //printf("length = %d\n\n",length);//temp


  //return the number parts in the string
  if(word == -1 || word == -2)
  {
    //count where all the "magic" characters are
    for(x = 0;x < length;x++)
    {
       d = subject[x];//copy the character value to d

       //printf("%c : %c =",d,magic);//temp

       //if the subject character = "magic" character then count it
       if(d == magic)
       {
         if(word == -2) { z++; } //increment z regardless of where magic is found for word -2

         a = x;//set a to x , to match where x is currently at.

         if(x == 0) { y++; }

         if(x > 0)
         {
           c = a - b;// c = the new count (of x) - the old count (of x)

           //a magic character must have a difference between it's last
           //position (if there is one) and its new position ( which is greater
           //than 1 ) to be counted as magic character. Therefore, if "#" is a
           //magic character and a string is, "##magic:" it would be discounted.
           //However, a string such as,"# #magic:" would be counted as two
           //magic characters.

           //When word == -2 an additional check that the same number of
           //magic characters found anywhere in subject are the same number
           //of magic characters that are at least spaced apart by at least 2
           //characters.

           if(c > 1) { y++; } // if c > 1 then increment y
         }

         b = a;//set b to a , to save the previous count (of x)

         //printf(" true : y = %d\n",y);//temp
       }
       else
       {
         //printf("false\n");//temp - do nothing
       }
    //end of for loop
    }

    if (word == -2) { if(z != y) { return -1; } }

    return y;
  }

  // just copy the string - a do nothing feature
  if(word == 0)
  {
    strcpy(target,subject);
    return 0;
  }

  //** this is where strtok() is used **

  /*
    note: strtok expects the token to be a cstring without a null character
          on the first use, and a token to be a cstring *with* a
          null character every use after the first.
  */

  //copy the first word in the string (must be done to find the next words)

  if(word == 1)
  {
    p = strtok(subject,w2);
    strcpy(target,p);
  }

  //copy the next word sequencially in the string as word increments by 1

  if(word > 1)
  {
    p = strtok(NULL,w1);
    strcpy(target,p);
  }

  return 0;
}

//generic prompt and get text from user
short int kfgets(char *target)
{
   short int a;//temp. variables
   char line[PARSE_SIZE_LIMIT]; line[0] = '\0'; //temp string storage

   //programmer must provide a prompt for whatever information wanted
   //from the user

   fgets(line ,PARSE_SIZE_LIMIT, stdin);
   a = strlen(line);
   line[a-1] = '\0';//get rid of the newline character added by fgets

   strcpy(target,line);//copy line to the target array

   return 0;
}

//a simple (yes/no) branch
short int ynreturn(void)
{

    short int result = 0;
    char x[3];

    while (fgets(x,3,stdin) != NULL && x[1] != '\n');

    switch(x[0])
    {
       case('Y'):
       case('y'):
       {
          result = 1;
          break;
       }

       case('N'):
       case('n'):
       {
          result = 0;
          break;
       }
       //for garbage
       default:
       {
          result = 0;
          break;
       }
    }

    return result;
}

//a ANSI C equivalent of " Press any key to continue "

short int return_key(void)
{
   char x[2];

   printf("\n Press Enter...\r");
   while (fgets(x,2,stdin) != NULL && x[0] != '\n');

   return 0;
}

(end of code)

Now, as previously stated, the program compiles fine ( I am using DJGPP for Windows 95 in MS-DOS ) and runs without a complaint. 

But when I implement it in my bigger program, called WATT... I get :

Exiting due to signal SIGSEGV
General Protection Fault at eip=000093a3
eax=49420001 ebx=0001b500 ecx=00000000 edx=00000006 esi=0001b5b4 edi=0009d5c4
ebp=0009d508 esp=0009d4a0 program=C:\DJGPP\PROGRAMS\WATT.EXE
cs: sel=0187  base=8395b000  limit=000bffff
ds: sel=018f  base=8395b000  limit=000bffff
es: sel=018f  base=8395b000  limit=000bffff
fs: sel=0167  base=000113b0  limit=0000ffff
gs: sel=019f  base=00000000  limit=0010ffff
ss: sel=018f  base=8395b000  limit=000bffff
App stack: [0009d7f0..0001d7f0]  Exceptn stack: [0001d74c..0001b80c]

Call frame traceback EIPs:
  0x000093a3
  0x000065c5
  0x00005d0e
  0x0000bd68

(end of message) 

As you can see, from parstext.c strtok() is returning a NULL pointer which is not being checked for in either program. So I am trying to figure out why the parstext.c program is not triggering this General Protection Fault message?

Thanks.

KJW




- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019