LinuxQuestions.org
Help answer threads with 0 replies.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 05-23-2009, 09:12 PM   #1
turriff
LQ Newbie
 
Registered: Aug 2008
Posts: 3

Rep: Reputation: 0
Confused by gcc


I'm teaching myself how to use gcc. I've written a simple function and a main program to test it. They both seem to compile clean, but when I run the test program it gets a segfault. If I run it with gdb I see an error message, but I'm not sure what it's trying to tell me.
Here's the function:

Code:
/* isABBRev - Compares two strings, returning 1 if the second string is an */
/* abbreviation of the first string, otherwise 0. */
/* */
/* Synopsis: int isABBRev(char *STRing1, char *string2); */
/* */
/* The minimum number of characters that must match is determined */
/* by the number of leading uppercase characters in the first */
/* string. If all characters of the second string match the */
/* leftmost characters of the first string (regardless of case), */
/* the second string is an abbreviation of the first string. */
 
#include <ctype.h>
#include <string.h>
#define ARBMAX 50
 
int isABBRev(char* fullWord, char* testWord)
 {int minLength = 1;
  int rc;
  char *c;
 
/* Count leading uppercase characters to determine the minimum abbreviation. */
  c = fullWord;
 
  while (!islower(c))
   {minLength++;
    c++;
   };
 
  if (strlen(testWord) > ARBMAX) /* abbreviation is too long. */
    return(0);
 
  if (strlen(testWord) > strlen(fullWord)) /* abbreviation is too long. */
    return(0);
 
  if (strlen(testWord) < minLength) /* abbreviation is too short. */
    return(0);
 
  rc = strncasecmp(testWord, fullWord, strlen(testWord));
  return(rc == 0);
 }
Here's the test program:

Code:
  
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int isABBRev(char*, char*)
/* ------------------------------------------------------------------------*/
int main(int argc, char *argv[])
 {int rc;
 
  if (argc != 3)
   {printf("Usage: testABBRev: FULLword abbreviation\n");
    printf(" where the uppercase part of FULLword indicates\n");
    printf(" the minimum abbreviation length allowed.\n");
    return 12;
   }
  rc = isABBRev(argv[1], argv[2]);
 
  if (rc == 0)
   {printf("%s is not an abbreviation of %s.\n", argv[2], argv[1]);
    return 4;
   }
  else
   {printf("%s is an abbreviation of %s.\n", argv[2], argv[1]);
    return 0;
   }
 }
Compile commands look like this:

Code:
  
$gcc -Wall -c -g isABBRev.c testABBRev.c
$gcc -Wall -o testABBRev isABBRev.o testABBRev.o
Neither of them produce any error messages.
Execution of testABBRev looks like this:

Code:
  
$./testABBRev HISTory hist
 Segmentation fault
Execution via gdb shows this:

Code:
  
$gdb testABBRev
GNU gdb 6.8
 Copyright (C) 2008 Free Software Foundation, Inc.
 License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
 This is free software: you are free to change and redistribute it.
 There is NO WARRANTY, to the extent permitted by law. Type "show copying"
 and "show warranty" for details.
 This GDB was configured as "i586-suse-linux"...
 (gdb) break main
 Breakpoint 1 at 0x80485bc: file testABBRev.c, line 10.
 (gdb) run HISTory history
 Starting program: /home/turriff/Documents/Code/Linux-pipelines/testABBRev HISTory history
 
 Breakpoint 1, main (argc=3, argv=0xbfc8ad54) at testABBRev.c:10
 10 if (argc != 3)
 (gdb) step
 16 rc = isABBRev(argv[1], argv[2]);
 (gdb) step
 isABBRev (fullWord=0xbfc8b319 "HISTory", testWord=0xbfc8b321 "history")
 at isABBRev.c:17
 17 {int minLength = 1;
 (gdb) step
 22 c = fullWord;
 (gdb) step
 24 while (!islower(c))
 (gdb) step
 __ctype_b_loc () at ../include/ctype.h:27
 27 ../include/ctype.h: No such file or directory.
 in ../include/ctype.h
 (gdb) finish
 Run till exit from #0 __ctype_b_loc () at ../include/ctype.h:27
 0x080484f7 in isABBRev (fullWord=0xbfc8b319 "HISTory",
 testWord=0xbfc8b321 "history") at isABBRev.c:24
 24 while (!islower(c))
 Value returned is $1 = (const short unsigned int **) 0xb7f0468c
 (gdb) step
 
 Program received signal SIGSEGV, Segmentation fault.
 0x08048501 in isABBRev (fullWord=0xbfc8b319 "HISTory",
 testWord=0xbfc8b321 "history") at isABBRev.c:24
 24 while (!islower(c))
 (gdb)
 :
According to man isupper (which lumps a bunch of function descriptions together):

Code:
  
 ISALPHA(3) Linux Programmer's Manual ISALPHA(3)
 
 
 
 NAME
 isalnum, isalpha, isascii, isblank, iscntrl, isdigit, isgraph, islower,
 isprint, ispunct, isspace, isupper, isxdigit - character classification
 routines
 
 SYNOPSIS
 #include <ctype.h>
 
 int isalnum(int c);
 int isalpha(int c);
 int isascii(int c);
 int isblank(int c);
 int iscntrl(int c);
 int isdigit(int c);
 int isgraph(int c);
 int islower(int c);
 int isprint(int c);
 int ispunct(int c);
 int isspace(int c);
 int isupper(int c); <====
 int isxdigit(int c);
 :
Looks to me like isupper() should return an int, but gdb says it's returning a const short unsigned int. Is this what is causing the segfault? If so, what should I do to correct the problem?

Leslie

BTW, if this is not the right place to ask such a question, can you recommend another place?
 
Old 05-23-2009, 11:07 PM   #2
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,780

Rep: Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081
Code:
  while (!islower(c))
   {minLength++;
    c++;
   };
2 problems here:

islower takes an int as you can see in the man page, but you passed it c which is a char*. Lower down the man page it says:
Code:
DESCRIPTION
       These  functions  check  whether  c,  which  must  have the value of an
       unsigned char or EOF, falls into a certain character class according to
       the current locale.
The c there refers to the int c parameter to the function, not your char *c. Since you passed an address which almost certainly does not have a value of unsigned char or EOF (-1), the behaviour of islower is undefined. Taking a peek at the implementation, we see it uses an array as a lookup table, passing a large number like an address causes the lookup to go out of range generating a segfault (I think the lookup table is the source if the unsigned int** you saw in gdb). Also note that it's a macro that explictly casts c to an int, which explains why the compiler didn't give you a warning about this.

Second problem: after you fix the above by doing
Code:
  while (!islower(*c))
Consider what would happen if fullWord was all uppercase.

Quote:
24 while (!islower(c))
(gdb) step
__ctype_b_loc () at ../include/ctype.h:27
27 ../include/ctype.h: No such file or directory.
in ../include/ctype.h
A tip: there's not much point in stepping into library functions (unless you're the library writer and you have the debugging symbols for the library), use next instead of step to stay on the same level of code.
 
Old 05-25-2009, 09:49 PM   #3
turriff
LQ Newbie
 
Registered: Aug 2008
Posts: 3

Original Poster
Rep: Reputation: 0
ntubski,

Thank you very much. I suppose that I will eventually get straight the methods for accessing the characters in strings.

Also, thanks for pointing out 'next' vs 'step' in gdb.

Leslie
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Compile error, 'H5G_obj_t' does not name a type, is gcc 4.3 incompatible with gcc 3 ? samrat_rao Linux - Software 5 03-03-2009 02:28 PM
yum install gcc doesn't set the lastest gcc ver 4.3.x kim,jw Linux - Newbie 3 12-22-2008 11:51 PM
Confused nay Very Confused chrystlenight SUSE / openSUSE 3 08-28-2007 05:57 PM
gcc wont install, 'failed dependencies: glibc-devel is needed by gcc-3.3.3-41' TdlSnare SUSE / openSUSE 3 11-29-2004 02:13 PM
export CC=/usr/bin/gcc-3.2 - switch gcc version? ferreter Linux - Software 1 08-20-2003 12:07 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 03:58 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration