X-Authentication-Warning: delorie.com: mail set sender to djgpp-bounces using -f From: "Rod Pemberton" 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: 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" 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 > #include > > // 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