delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2013/06/17/19:00:10

X-Authentication-Warning: delorie.com: mail set sender to djgpp-bounces using -f
From: "Rod Pemberton" <do_not_have AT notemailnotq DOT cpm>
Newsgroups: comp.os.msdos.djgpp
Subject: Re: General Protection Fault error is intermittent
Date: Mon, 17 Jun 2013 18:48:36 -0400
Organization: Aioe.org NNTP Server
Lines: 293
Message-ID: <kpo3gh$4qo$1@speranza.aioe.org>
References: <36e857f0-9899-496b-9fc6-32251e109888 AT googlegroups DOT com>
NNTP-Posting-Host: CNsg4fVcCsvs3UaOgZtQCw.user.speranza.aioe.org
X-Complaints-To: abuse AT aioe DOT org
X-Notice: Filtered by postfilter v. 0.8.2
X-Newsreader: Microsoft Outlook Express 6.00.2800.2001
X-Priority: 3
X-MSMail-Priority: Normal
X-MIMEOLE: Produced By Microsoft MimeOLE V6.00.2800.2001
Bytes: 9196
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp
Reply-To: djgpp AT delorie DOT com

"K.J.Williams" <lordwilliams1972 AT gmail DOT com> wrote in message
news:36e857f0-9899-496b-9fc6-32251e109888 AT googlegroups DOT com...
>
> 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 ?

This looks just a bit like homework to me...  Is it?

Have you found the problem(s) yet?

What have you tried?

My first guess would be that you're using strtok() in your large
program too.  Check to see if your larger program's code is using
strtok() also.  That could be an issue.

My next guess would be that your buffers sizes are too small or
incorrect.  Does changing PARSE_SIZE_LIMIT to a larger value, say
512 or 4096, fix the problem?  If so, your buffers are too small.

Does eliminating most usage of printf()'s eliminate the problem?
Or, does using printf()'s eliminate the problem?  If the problem
appears or disappears with usage of printf(), you have a memory
allocation or leak problem somewhere.  For some odd reason,
DJGPP's printf() will reveal memory allocation issues.  Sometimes
using it will eliminate the crash.  Other times using it will
cause the crash.  In both cases, it's something wrong with memory
allocation or buffer overflow, etc.

Does using the C library's fgets() instead of kfgets() eliminate
the issue?  If so, something in kfgets() is at fault.

Have you verified the range represented by y and z are correct?

Have you verified that counta and countb are correct?

Other suggestions or possible issues in the code below.

> [here is] 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
>

#define PARSE_SIZE_LIMIT 81

This should probably be split into two defines.   This is to make
sure the allocated buffer or character array is _always_ larger
than the quantity read or written to the buffer.  Use one define
for the character arrays and another for the buffer size.  They
should be slightly larger by at least two chars for the DOS
newline:

 #define PARSE_SIZE_LIMIT 80
 #define BUFFER_SIZE 82

So, any place you declare a variable that used PARSE_SIZE_LIMIT,
it would be changed to use BUFFER_SIZE:

Change:
 char variable[PARSE_SIZE_LIMIT]

To:
 char variable[BUFFER_SIZE]

This would be done for the declarations of the following
variables:
 target, worda, uword in main()
 subject in string_parser()
 line in kfgets()

Leave the other non-declaration uses of PARSE_SIZE_LIMIT alone.

> [SNIP]
>
> int main (void)
> {
>    //declare char arrays and initialize garbage with '\0'
>
> [SNIP]
>
>    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");
>

The word "statement" in main() has two letter e's, not just one,
i.e., misspelled...

>    //prompt user
>
>     do
>     {
>
>     //initialize (or reset) these variables
>     z = 1;
>     target[0] = '\0';
>
> [SNIP]
>
>         if(countb > 1)
>         {
>           for(y = 1;y <= countb;y++)
>           {
>              string_parser(worda,uword,' ',y);
>              printf("...sub-part#%d : %s\n",y,uword);
>           }
>         }
>
>       //pause

z++;

See below.

>       if(z < counta); { return_key(); }

This appears to have a bug.  There is an extra semi-colon between
what appears to be the correct body of the if() and the if's
condition.  Removed semicolon:

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

>
>       z++;

Z appears to be off by one for the if() above.  I moved it up
above.

> [SNIP]
>
> //parses c strings by using single character tokens with
> strtok();
> short int string_parser(char *userstring, char *target, char
> magic, short int word)
> {

Since "magic" is only one character, it's probably easier if you
used strchr() or strrchr() to parse instead of using strtok().

>   char subject[PARSE_SIZE_LIMIT]; subject[0] = '\0';
> //initialize subject
>
>   //w1 = token with null character ; w2 = token without null
> character

Remove comment for w2.  It's wrong.  Or, change to same comment as
w1.  A null character, i.e., '\0' in C, and a NULL pointer are
completely different.

>   char w1[2]; w1[0] = magic; w1[1] = '\0';
>   char w2[1]; w2[0] = magic;
>

It appears that there are two bugs here.  w2 in string_parser is a
standard string.  It should be null terminated, like w1.  It
should also have enough space for two characters.  I.e.,
string_parser() needs this here:

   char w2[2]; w2[0] = magic; w2[1]='\0';

>   //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
>
> [SNIP]
>
>          //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; } }
>

y++;

Y seems to be off by one.

> [SNIP]
>   //** 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.
>   */
>

No...

strtok() expects the first argument to be a valid pointer to char,
i.e., char *, for the first call.  strtok() expects the first
argument to be a NULL pointer to continue processing the same
token for additional calls.  Your use of strtok() in the code
below that comment appears correct.

> [SNIP]
> //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
>

I'm not sure how you're detecting the final argument.  You might
be checking for a '\0' somewhere with strtok(), but I didn't see
that.  If so, it doesn't seem to be working...  But, space padding
the string here in kfgets() will allow you parse the final arg.

Comment out:
  line[a-1]='\0';

Add:
  line[a-1]=' ';
  line[a]='\0';

FYI, this is probably not the fix you want...

> [SNIP]
>
> //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_key() attempts to get two characters, but checks for one...
Two characters for newline under DOS ( '\r\n') would require stdin
to be set to binary mode.  Off hand, I don't recall if stdin is
set to binary mode or text mode, but I suspect it's text since I
generally use binary mode and check for two...  I.e., one
character ('\n') is all I think you should need to get.

It seems you're using fgets() to read just a few characters in
multiple places?  Why not just use getc() or getch()?  Was this in
preparation for your kfgets() read routine?

That's definately not everything, but it's a start.


Rod Pemberton



- Raw text -


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