Thread: segmentation fault... first time with unix...

  1. #1
    Registered User
    Join Date
    Sep 2008
    Posts
    12

    segmentation fault... first time with unix...

    I have never programmed in C on UNIX earlier and the first time I did returned some surprising results. I first coded the programmed in Turbo C in Windows and it compiled and executed perfectly well. Then I compiled the program in GCC in UNIX and some surprise I got when I learned a new thing called "Segmentation Fault". The programmed compiled with just a warning against using "gets" function and produced an executable. Running it, I encounter "Segmentation Fault" and the program terminates whenever (as I discovered through running the program couple of times) either the character array is tokenized or the pointer token's string is copied into an empty character array: don't know exactly which one of them is causing the trouble! I have never used UNIX before and have absolutely no idea what to do! Here's my code and also the exact output:-

    Code:
    //declaring preprocessor directives
    #include <stdio.h>
    #include <string.h>
    
    //method to validate user's input as  a legal Mynix command
    int parseInput(char checkCommand[])
    {
    	int counter;
    	char *inputToken, tempString[30];
    
    	//loop to verify any character in the input is either a small alphabet or a hyphen or a space
    	for (counter= 0; counter<strlen(checkCommand); counter++)
    	{
    		if (checkCommand[counter]<'a' || checkCommand[counter]>'z')
    		{
    			if (checkCommand[counter]!='-' && checkCommand[counter]!=' ')
    			{
    				printf("mynix> - No such thing!");
    				return 0;
    			}
    		}
    	}//character verification loop ends here
    
    	//checking if input is an exit command
    	if (strcmp(checkCommand, "exit")==0)
    	{
    		return 1;	//returning a non-zero value to exit the do-while loop in main
    	}
    
    	//checking for commands that can work without (or do not need) any switch or parameter like 'cd', 'ls', 'pwd' and 'cat'
    	else if(strcmp(checkCommand, "cd")==0 || strcmp(checkCommand, "ls")==0 || 
    	        strcmp(checkCommand, "pwd")==0 || strcmp(checkCommand, "cat")==0)
    	{
    		printf("mynix> - Done!");
    		return 0;
    	}
    
    	//checking for commands that can have (or need) switches or parameters like 'cd', 'ls', 'cat', 'man', 'mkdir', 'whereis'
    	else
    	{
    		inputToken= strtok(checkCommand, " ");	//tokenizing by space for first part
    		
    		//checking first token for a valid command
    		if (strcmp(inputToken, "man")==0 || strcmp(inputToken, "ls")==0 || 
    		    strcmp(inputToken, "cd")==0 || strcmp(inputToken, "mkdir")==0 || 
    		    strcmp(inputToken, "cat")==0 || strcmp(inputToken, "whereis")==0)
    		{
    			inputToken= strtok(NULL, " ");	//tokenizing by space for second part
    			strcpy(tempString, inputToken);	//storing token's value in a string
    
    			//checking that second part does not start with a hyphen and that its a valid parameter
    			if (tempString[0]!='-' && strlen(tempString)>0)
    			{
    
    				inputToken= strtok(NULL, " ");	//tokenizing by space for third part
    				strcpy(tempString, inputToken); //storing token's value in a string
    
    				//checking that there is no third part after a parameter
    				if (strcmp(tempString, NULL)==0)
    				{
    					printf("mynix> - Done!");
    					return 0;
    				}
    
    				else
    				{
    					printf("mynix> - No such thing!");
    					return 0;
    				}
    			}//third part verification ends here
    
    			//checking validity if second part starts with a hyphen
    			else
    			{
    				//checking that there is only one character after a hyphen in the second part
    				if (strlen(tempString)==2)
    				{
    					inputToken= strtok(NULL, " ");	//tokenizing by space for third part
    					strcpy(tempString, inputToken);	//storing token's value in a string
    
    					//checking that after a valid switch the third part does not start with a hyphen
    					if (tempString[0]!='-' && strcmp(tempString, NULL)!=0)
    					{
    						inputToken= strtok(NULL, " ");	//tokenizing by space for fourth part
    						strcpy(tempString, inputToken);	//storing token's value in a string
    
    						//checking that there is no fourth part
    						if (strcmp(tempString, NULL)==0)
    						{
    							printf("mynix> - Done!");
    							return 0;
    						}
    
    						//if more than three parts are there in the command
    						else
    						{
    							printf("mynix> - No such thing!");
    							return 0;
    						}
    					}
    					
    					//if parameter is incorrectly declared
    					else
    					{
    						printf("mynix> - No such thing!");
    						return 0;
    					}
    				}
    				
    				//if switch is incorrectly delcared
    				else
    				{
    					printf("mynix> - No such thing!");
    					return 0;
    				}
    			}//second part verification if-else ladder ends here
    		}
    		
    		//if first part not valid then
    		else
    		{
    			printf("mynix> - No such thing!");
    			return 0;
    		}//first part verification if-else ladder ends here
    	}//total command verification if-else ladder ends here
    }//method parseInput ends here
    
    //main method begins here
    int main()
    {
    	char userInput[30];
    	int exitVariable= 0;
    
    	//do-while loop to prompt user for next command till exit command is executed
    	do
    	{
    		printf("\nmynix> ");
    
    		gets(userInput);
    
    		exitVariable= parseInput(userInput);
    	}
    	while(exitVariable==0);
    	//do-while loop ends here
    	
    	return 0;	//no value required to be returned by main method
    }//main method ends here
    //program ends here
    The output is:-

    Code:
    mynix> hey
    mynix> - No such thing!
    mynix> ls
    mynix> - Done!
    mynix> ls -a
    Segmentation fault
    Please help! Thanks a lot for taking out some time!
    Last edited by Salem; 09-30-2008 at 11:39 AM. Reason: Fold long lines for readability

  2. #2
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    Well I see a lot of little issues with your code. Why not just use strtok()? It would not lead to the buffer overlflow issues you could have with your whole tempString mumbo-jumbo.

  3. #3
    The superhaterodyne twomers's Avatar
    Join Date
    Dec 2005
    Location
    Ireland
    Posts
    2,273
    >> gets(userInput);
    Not really smiled upon. See here why.

  4. #4
    Registered User
    Join Date
    Sep 2008
    Posts
    12
    master5001 thanks for taking out so much time! Could you please have a chat with me? I'll be really grateful! If you don't mind then please add user "matereality" on gtalk; I am online right now.

    Anyway if you are not comfortable with it then no problem. But could you please ellaborate a bit what exactly I need to do? As you can see I have used strtok() couple of times. Please guide a little further and kindly explain what exactly could the issues be with tempString?
    Thankyou very much!

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    You probably should be more careful with the result of strtok() - it can be NULL...
    Code:
    						inputToken= strtok(NULL, " ");	//tokenizing by space for fourth part
    						strcpy(tempString, inputToken);	//storing token's value in a string
    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  6. #6
    Registered User
    Join Date
    Sep 2008
    Posts
    12
    matsp I tried running the program after removing that part entirely. The string only gets tokenized twice now; and even after inputs with exactly three parts separated by space segmentation fault still shows up!
    Here's the output:-

    Code:
    mynix> cd
    mynix> - Done!
    mynix> cd -i sdf
    Segmentation fault

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Code:
    strcmp(tempString, NULL)
    Whilst looking over the code again, this stands out like an "instant" crash line - passing NULL to strcmp will deifnitely not work.

    But this should really be a learning experience in debugging. It's not a hard problem to solve, you just need to track down where you are using an invalid pointer - a few minutes with a few added printf shoudl do it.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #8
    Registered User
    Join Date
    Sep 2008
    Posts
    12
    Well this is for everyone reading this post... firstly I am seriously grateful for taking some time out to read it!
    Now what I wish to do with this program is to develop a kind of Unix shell simulator. Simple enough. This works flawlessly in Turbo C in Windows. These segfaults are only occurring in GCC in Unix and since I have never programmed in Unix before I find these pretty HARD to understand and remove. Moreover, is there any other way to do this program the way I have done it without getting any segfaults? Obviously I am not going to get rid of all string functions and pointers and start making arrays after arrays to compare character by character.

    Please help! I am not asking anyone to code the entire program correctly for me. I am just asking to please elaborate your suggestion or advice only after checking yourself that it works; because (please pardon me for saying this) none has worked yet!

    Thanks a lot again!

  9. #9
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    If strcmp(whatever, NULL) doesn't crash Turbo C, then Turbo C is more broken than I thought (and I thought it was pretty darn broken). If you want the line that matches the comment //checking that there is no fourth part, then you want strcmp(whatever, ""), not strcmp(whatever, NULL) -- or if whatever is a return from strtok, you can just compare whatever with NULL directly, not using strcmp.

  10. #10
    Registered User
    Join Date
    Sep 2008
    Posts
    12
    tabstop I replaced strcmp(whatever, NULL) statements with strcmp(whatever, ""). While running through there is no fault at strcmp anymore but the ones with strcpy still exist! Can you help some more please? Thank you!

    Code:
    mynix> man -s sdf
    
    Program received signal SIGSEGV, Segmentation fault.
    0x00c70b40 in strcpy () from /lib/libc.so.6

  11. #11
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Again, the thing that comes back from strtok could be NULL, so right after you do strtok, you should do something like
    Code:
    if (inputToken==NULL) {
        // print "Done!" since we've read all the tokens
        // continue; or something similar so that we don't keep trying to read tokens
    }
    This probably means you also don't have to do the strcmp's with "" either, since I'm guessing that's what that check was for.

  12. #12
    Registered User
    Join Date
    Sep 2008
    Posts
    12
    Ok here's an update: I replaced all "strcpy(tempString, inputToken);" statements with "strncpy(tempString, inputToken, strlen(inputToken));". Now the program doesn't recognize a string as legal that is supposed to be legal! Plus it pops out the fault here...


    Code:
    mynix> man -d df
    mynix> - No such thing!
    mynix> man
    
    Program received signal SIGSEGV, Segmentation fault.
    0x080487b6 in parseInput (checkCommand=0xbfc2f572 "man") at mynixTemp.c:54
    54                              strncpy(tempString, inputToken, strlen(inputToken));    //storing token's value in a string

  13. #13
    Registered User
    Join Date
    Sep 2008
    Posts
    12
    tabstop thanks a lot indeed! That REALLY worked! There's just one small trouble left now... the program does not pass legal inputs as legal... here's the run... please check! THANKS A LOT!

    Code:
    mynix> man
    mynix> - No such thing!
    mynix> man -p sdf
    mynix> - No such thing!
    mynix> cd
    mynix> - Done!
    mynix> cd -d sd
    mynix> - No such thing!
    mynix> cd -d
    mynix> - No such thing!
    mynix> ls a
    mynix> - No such thing!
    mynix> exit
    
    Program exited normally.

  14. #14
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    It could be handy to make your error messages slightly different (at least temporarily) so that you can see how your program flow is going.

  15. #15
    Registered User
    Join Date
    Sep 2008
    Posts
    12
    I am really grateful to everyone to who has contributed their time to this post! Thank you very much everyone; especially you tabstop! There are NO segfaults now!

    Well the only thing is that now the program is not accepting strings that it should! The sweetest part is that I can't figure out what to do!

    The output is given in the previous post.

    Thanks! It's almost done!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Why am I getting segmentation fault on this?
    By arya6000 in forum C++ Programming
    Replies: 6
    Last Post: 10-12-2008, 06:32 AM
  2. Re: Segmentation fault
    By turkish_van in forum C Programming
    Replies: 8
    Last Post: 01-20-2007, 05:50 PM
  3. Replies: 7
    Last Post: 12-10-2004, 01:58 AM
  4. Segmentation fault...
    By alvifarooq in forum C++ Programming
    Replies: 14
    Last Post: 09-26-2004, 12:53 PM
  5. strcat segmentation fault
    By captain-cat in forum C Programming
    Replies: 3
    Last Post: 07-20-2004, 10:29 AM