Segmentation Fault in CentOS5

Programming, for all ages and all languages.
Post Reply
osmiumusa
Posts: 20
Joined: Sun Dec 12, 2010 5:47 pm

Segmentation Fault in CentOS5

Post by osmiumusa »

Hello,

I'm writing a program called "peek" that takes a couple of parameters, such as a file, and displays a bit of the file. The code looks like it will work, but when I run it, even without arguments, I get a "Segmentation Fault" message instead of what its supposed to print out.

I tried to debug it with GDB but it doesn't seem to want to tell me anything useful. It tells me the error, but beyond that, it doesn't tell me much else. I can't do a backtrace as the problem seems to be in the main() function. I think it has something to do with the file functions, but I'm not sure.

This program is written in C, and uses the functions "fopen, fclose, fgets, atoi, printf, strcat"
Compiled with "gcc peek.c" and puts out "a.out"
Executed with "./a.out <arguments>"

I'll show source code as a worst-case scenario, but I'm the kind of person who is reluctant to do so... I've had some bad experiences with that...

Thank you so much in advance for any help.

~osmiumusa :mrgreen:
User avatar
JackScott
Member
Member
Posts: 1031
Joined: Thu Dec 21, 2006 3:03 am
Location: Hobart, Australia
Contact:

Re: Segmentation Fault in CentOS5

Post by JackScott »

Could you please paste the output from GDB (the error message)? That would probably be the best start. The code would also be really helpful. Can I ask why you have bad experiences with showing it?

In my personal experience, "Segmentation Fault" usually indicates a bad pointer dereference. But not always.

You could also try my favourite debugging method: put calls to printf() with numbers or short messages (i.e. 'printf("got to the bit where i open the file\n")') in between every major function call or part where you suspect the code of failing, and then seeing where the output gets to before it crashes.
osmiumusa
Posts: 20
Joined: Sun Dec 12, 2010 5:47 pm

Re: Segmentation Fault in CentOS5

Post by osmiumusa »

Code: Select all

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

int main(int, char**);
void color_settopaper();
void color_revert();
void newline();
void done(int);
void stripnl(char *);
void color_warning();
void help();
int usecolor = 1;

//usage "peek <file> -m <linecount> --nocolor

//BEGIN ACTUALL CODE
int main(int argc, char** argv) {
	//defaults and declarations
//	int usecolor = 1;
	int maxcount = 10; 
	int lcount = 0;
	if (argc==1) {done(1);}
	//parse the arguments...
	int i=0;
	
	for (i=2;i<=argc;i++) {
		if (!strcmp(argv[i],"-m")) {
			maxcount = atoi(argv[(i+1)]);
			i++;
			continue;
		}
		if (!strcmp(argv[i],"--nocolor")) {
			usecolor = 0;
			continue;
		}
		if (!strcmp(argv[i],"-l")) {
			lcount = atoi(argv[(i+1)]);
			i++;
			continue;
		}
		if (!strcmp(argv[i],"--help")) {
			help();
			continue;
		}
		color_warning();
		printf("You passed me an invalid switch: %s. I'll ignore it this time but ",argv[i]);
		color_error();
		printf("DON'T LET IT HAPPEN AGAIN!");
		color_revert();
		printf(" Thanks!");
		newline();
	}

	color_settopaper();
	FILE *infile;
	char line[100];
	/* Read in the filename */
	/* We need to get rid of the newline char. */
	stripnl(argv[1]);
	/* Open the file.  If NULL is returned there was an error */
	if((infile = fopen(argv[1], "r")) == NULL) {
		done(2);
	}
  
	while(fgets(line, sizeof(line), infile) != NULL || lcount>maxcount) {
		/* Get each line from the infile */
		lcount++;
		/* print the line number and data */
		printf("Line %d: %s", lcount, line);  
  	}
 
	fclose(infile);  /* Close the file */

	color_revert();
	done(0); //finish with no error
}

void stripnl(char *str) {
  while(strlen(str) && ( (str[strlen(str) - 1] == 13) || 
       ( str[strlen(str) - 1] == 10 ))) {
    str[strlen(str) - 1] = 0;
  }
}
void color_warning() {
	printf("\033[31;42m");
}
void color_settopaper() {
	if (usecolor) printf("\033[30;47m");
}
	
void color_revert() {
	if (usecolor) printf("\033[0m");
}

void color_error() {
	if (usecolor) printf("\033[1;33;41m");
}
void newline() {
	printf("\n");
}
void help() {
	printf("Let colors be enabled if possible for this help message");
	newline();
	printf("Peek allows you to peek at a file without seeing the entire thing");
	newline();
	printf("Peek does not clear the entire screen");
	newline();
	printf("Usage:");
	newline();
	printf("	peek <filename> [-m <numberoflines> -l <startingline> --nocolor --help");
	newline();
	printf("You MUST specify a file name to peek at!");
	newline();
	printf("Options:");
	newline();
	printf("-m <numberoflines>	<numberoflines> specifies how many lines to peek at. The default is 10.");
	newline();
	printf("-l <startingline>	<startingline> specifies where to start in the file. The default is at the begining.");
	newline();
	printf("--nocolor		Disables the use of color in the program's output.");
	newline();
	printf("--help			Displays this help file and quits.");
	newline();
	printf("If you pass the program an invalid switch, it may be rude about it.");
	newline();
	newline();
	color_settopaper();
	printf("This color");
	color_revert();
	printf(" is the \"paper\" color. The file will be this color");
	newline();
	color_warning();
	printf("This color");
	color_revert();
	printf(" is a warning color; not used often.");
	newline();
	color_error();
	printf("This color");
	color_revert();
	printf(" is the error color.");
	done(0);
}
void done(int errorcode) {
	if (errorcode==1) {
		color_error();
		printf("No file specified. Please specify a file.");
	}
	if (errorcode==2) {
		color_error();
		printf("Error opening the file specified. Make sure the source is readable");
	}
	color_revert();
	printf("\n");
	exit(1);
}
Here is what I do to exicute it and its respective outputs...

Code: Select all

[root@localhost peek]# ./a.out
No file specified. Please specify a file.
[root@localhost peek]# ./a.out foo.bar 
Segmentation fault
[root@localhost peek]# ./a.out foo.bar -m 7
Segmentation fault
And here is what GDB can tell me...

Code: Select all

[root@localhost peek]# gdb a.out
GNU gdb (GDB) Red Hat Enterprise Linux (7.0.1-37.el5_7.1)
Copyright (C) 2009 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 "i386-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/programs/peek/a.out...(no debugging symbols found)...done.
(gdb) run
Starting program: /root/programs/peek/a.out 
No file specified. Please specify a file.

Program exited with code 01.
(gdb) ru foo.dat
Starting program: /root/programs/peek/a.out foo.dat

Program received signal SIGSEGV, Segmentation fault.
0x08048894 in main ()
(gdb) backtrace
#0  0x08048894 in main ()
I can't seem to do anything else useful without a symbol file or a core dump. Any thoughts? It doesn't look like (to me) that I'm doing things that I shouldn't...
osmiumusa
Posts: 20
Joined: Sun Dec 12, 2010 5:47 pm

Re: Segmentation Fault in CentOS5

Post by osmiumusa »

I did what JackScott suggested and found that it was dying at...

Code: Select all

if (!strcmp(argv[i],"-m")) {
Whats wrong with this and how can I fix it?
User avatar
Minoto
Member
Member
Posts: 89
Joined: Thu May 12, 2011 7:24 pm

Re: Segmentation Fault in CentOS5

Post by Minoto »

osmiumusa wrote:I did what JackScott suggested and found that it was dying at...

Code: Select all

if (!strcmp(argv[i],"-m")) {
Whats wrong with this and how can I fix it?
Try printing the value of argc as you run the program with varying numbers of arguments. Then think about loop termination conditions.

Edit: and starting points, too, actually.
Those who understand Unix are doomed to copy it, poorly.
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: Segmentation Fault in CentOS5

Post by neon »

Code: Select all

for (i=2;i<=argc;i++)
There is an error here that could very well cause a seg fault in the last iteration of the loop. Think about it...
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
osmiumusa
Posts: 20
Joined: Sun Dec 12, 2010 5:47 pm

Re: Segmentation Fault in CentOS5

Post by osmiumusa »

I think I see the problem... its going past the array by atleast one. How do I fix this? By changing the operator to "<"?
User avatar
JackScott
Member
Member
Posts: 1031
Joined: Thu Dec 21, 2006 3:03 am
Location: Hobart, Australia
Contact:

Re: Segmentation Fault in CentOS5

Post by JackScott »

Try it and see! It's only a quick edit and a recompile if it goes wrong.

Hint: Yes, that will probably fix it.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Segmentation Fault in CentOS5

Post by Combuster »

If an array has 5 elements, they will be:
a[0] // 1st
a[1] // 2nd
a[2] // 3rd
a[3] // 4th
a[4] // 5th

and a[5] is the sixth element and therefore does not exist. Same goes for argv[argc] which does not exist either.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Post Reply