Segmentation Fault...and we have no clue why

Page 1 of 1

8 Replies - 3194 Views - Last Post: 25 January 2009 - 03:18 PMRate Topic: //<![CDATA[ rating = new ipb.rating( 'topic_rate_', { url: 'https://www.dreamincode.net/forums/index.php?app=forums&module=ajax&section=topics&do=rateTopic&t=82702&amp;s=da84de3dd1a42193468fa65d0f66f530&md5check=' + ipb.vars['secure_hash'], cur_rating: 0, rated: 0, allow_rate: 0, multi_rate: 1, show_rate_text: true } ); //]]>

#1 bytescribe

Reputation: 0
• Posts: 19
• Joined: 17-January 09

Segmentation Fault...and we have no clue why

Posted 25 January 2009 - 09:21 AM

Hi, again, everyone.

My boyfriend and I have come upon another exercise in the C++ book we're using that has thrown us for a loop (no pun intended).

It's been a couple chapters in that book since I last posted, and we're now on Chapter 5, "Reading and Writing Files." The exercise we're stuck on is about formatting text with 'getline.'

When we compile and run the following code, we get a segmentation fault, with no core dump, but there is no real reason that we can see, why there should be a seg. fault. We're not using pointers...we're using a recursive loop that does have an end, so we're puzzled.

Here's the code.

```#include <fstream>
#include <string>
#include <iostream>
using namespace std;

int main()
{
const int RANGE = 12;
string tab[ RANGE ];
int i = 0, j = 0;
cout << "Error opening input file" << endl;
return -1;
}
if ( ( i + 1 ) % 4 == 0 )
getline( reader, tab[ i++ ], '\n' );
else
getline( reader, tab[ i++ ], '\t' );
}
i = 0;

while( i < RANGE ){
cout << endl << "Record Number: " << ++j << endl;
cout << "Forename: " << tab[ i++ ] << endl;
cout << "Surname: " << tab[ i++ ] << endl;
cout << "Department: " << tab[ i++ ] << endl;
cout << "Telephone: " << tab[ i++ ] << endl;
}
return 0;
}
```

Also, we're running Ubuntu Hardy Heron with, of course the GNU g-plus-plus compiler.

Any thoughts?

Laterz,
Kat ^.^

Is This A Good Question/Topic? 0

Replies To: Segmentation Fault...and we have no clue why

#2 bodom658

• Villiage Idiom

Reputation: 114
• Posts: 1,123
• Joined: 22-February 08

Re: Segmentation Fault...and we have no clue why

Posted 25 January 2009 - 09:25 AM

is it possible that you had less or more than 12 people in the file?

#3 baavgai

• Dreaming Coder

Reputation: 7361
• Posts: 15,284
• Joined: 16-October 07

Re: Segmentation Fault...and we have no clue why

Posted 25 January 2009 - 09:43 AM

You have two possibilities for pain here. I'll comment them:
```#include <fstream>
#include <string>
#include <iostream>

using namespace std;

int main() {
const int RANGE = 12;
string tab[ RANGE ];
int i = 0, j = 0;

cout << "Error opening input file" << endl;
return -1;
}

// here you're reading until EOF
// but not checking if i>= RANGE
// which will blow out your array
// I don't even want to know what's up with this
// you'd be better off reading lines and going from there
// have you looking into using vector?
// arrays are SO C
if ( ( i + 1 ) % 4 == 0 )
getline( reader, tab[ i++ ], '\n' );
else
getline( reader, tab[ i++ ], '\t' );
}

// huh?  You don't know how many lines you read
// you might assume i==RANGE
// reseting i to zero, you'll never know
i = 0;

// whoa, you're just asking for pain
// suddenly you have j?  what does j mean?
while( i < RANGE ){
cout << endl << "Record Number: " << ++j << endl;
cout << "Forename: " << tab[ i++ ] << endl;
cout << "Surname: " << tab[ i++ ] << endl;
cout << "Department: " << tab[ i++ ] << endl;
cout << "Telephone: " << tab[ i++ ] << endl;
}
return 0;
}

```

Alright, you're reading some records. Break down the problem. Read in the entire line and then parse the line. It's tab delimited, shouldn't really be a big deal. Additionally, you have four fields in the record. Having a class or struct would be nice; no one likes magic array values.

Something like this might be nice:
```typedef struct RecordStruct {
string forename;
string surname;
string dept;
string phone;
} RecordType;

void printRecord(RecordType &rec) {
cout << "Forename: " << rec.forename << endl;
cout << "Surname: " << rec.surname << endl;
cout << "Department: " << rec.dept << endl;
cout << "Telephone: " << rec.phone << endl;
}

```

Good luck.

#4 bytescribe

Reputation: 0
• Posts: 19
• Joined: 17-January 09

Re: Segmentation Fault...and we have no clue why

Posted 25 January 2009 - 11:54 AM

Hi again...

What you posted was working code. Helpful, but not what the exercise intended.

Here is the code again, with our comments on what we know, and don't know.
```#include <fstream>
#include <string>
#include <iostream>
using namespace std;

/*We still don't entirely know what we are doing, so
*in our understanding with c++ and this exercise.
*/

/*The name of this exercise is "Formatting with getline"
*this exercise is supposed show usage of arguments with
*getline(), specifically how to make a delimiter to stop
*/
int main()
{
/*Here are the declarations which are easy enough
*to understand
*/
const int RANGE = 12;
string tab[ RANGE ];
int i = 0, j = 0;
//We know what this if statement does
cout << "Error opening input file" << endl;
return -1;
}
/*This 'while' (according to the tutorial book we bought)
*is supposed to demonstrate the usage of two delimiters.
*One is \n and one is \t (new line and tab respectively)
*how this works is the line -
*if ( ( i + 1 ) % 4 == 0 ) - checks to see if
*the remainder of i plus one divided by four equals zero.
*if it does we get tab strings that delimit at the new line
*else we get tab strings that delimit at tabs
*(there are some assumptions made here)
*/
if ( ( i + 1 ) % 4 == 0 )/*Here we had changed the modulus
*to a division and got output but
*wrongly formatted.
*/
getline( reader, tab[ i++ ], '\n' );
else
getline( reader, tab[ i++ ], '\t' );
}
i = 0;
/*This while prints out the separated results from
*the text file that was read.
*We still don't know what the variable 'j' is for.
*Quentin has made a guess that
*j increments while i is less than range.
*/
while( i < RANGE ){
cout << endl << "Record Number: " << ++j << endl;
cout << "Forename: " << tab[ i++ ] << endl;
cout << "Surname: " << tab[ i++ ] << endl;
cout << "Department: " << tab[ i++ ] << endl;
cout << "Telephone: " << tab[ i++ ] << endl;
}
return 0;
/*The contents of the text file look like this

John	Smith	Sales	555-1234
Mary	Jones	Wages	555-9876
Paul	Harris	Accts	555-4321

*/

/*in the while statement we took out the modulus and used
a division symbol. The results printed are:

Record Number: 1
Forename: John	Smith	Sales	555-1234
Surname: Mary	Jones	Wages	555-9876
Department: Paul	Harris	Accts	555-4321
Telephone:

Record Number: 2
Forename:
Surname:
Department:
Telephone:

Record Number: 3
Forename:
Surname:
Department:
Telephone:
*/
}
```

Thanks again for helping!

Laterz,
Kat ^.^

#5 buckrogers1965

• New Member

Reputation: 9
• Posts: 87
• Joined: 23-January 09

Re: Segmentation Fault...and we have no clue why

Posted 25 January 2009 - 11:57 AM

bytescribe, on 25 Jan, 2009 - 08:21 AM, said:

When we compile and run the following code, we get a segmentation fault, with no core dump, but there is no real reason that we can see, why there should be a seg. fault. We're not using pointers...we're using a recursive loop that does have an end, so we're puzzled.

This is why I love debuggers.

Compile your program with a -g flag, and drop the -O followed by a number flag from the gcc line. This compiles the executable with a lot more symbol information so it can work with the debugger better.

Then instead of running the bare executable, type:

gdb exec

Where exec is the name of the command you used to use to run the program. gdb stands for GNU debugger.

Then type run
at the prompt, press enter, and the program will run normally until it core dumps.

At that point type bt
for back trace and it will show the stack track with what line the exec was on at each level.

You can type up and down to move up and down the stack track and type print variable_name to examine a variable. You can type list
to see the code around the place the debugger is looking at the time.

At that same prompt you typed run at before you can also type:

break function_name

or

break line_number

Where function_name is the name of one of your functions, or line_number where that is a line number in your source code.

Then type run and the debugger will stop each time you hit that line number or call that function.

Type:

cont

or

step

to keep running from a break point. Step goes one line at a time, while cont just takes off running again.

Hope this helps.

This post has been edited by buckrogers1965: 25 January 2009 - 12:03 PM

#6 bytescribe

Reputation: 0
• Posts: 19
• Joined: 17-January 09

Re: Segmentation Fault...and we have no clue why

Posted 25 January 2009 - 12:33 PM

buckrogers1965, on 25 Jan, 2009 - 10:57 AM, said:

bytescribe, on 25 Jan, 2009 - 08:21 AM, said:

When we compile and run the following code, we get a segmentation fault, with no core dump, but there is no real reason that we can see, why there should be a seg. fault. We're not using pointers...we're using a recursive loop that does have an end, so we're puzzled.

This is why I love debuggers.

Compile your program with a -g flag, and drop the -O followed by a number flag from the gcc line. This compiles the executable with a lot more symbol information so it can work with the debugger better.

Then instead of running the bare executable, type:

gdb exec

Where exec is the name of the command you used to use to run the program. gdb stands for GNU debugger.

Then type run
at the prompt, press enter, and the program will run normally until it core dumps.

At that point type bt
for back trace and it will show the stack track with what line the exec was on at each level.

You can type up and down to move up and down the stack track and type print variable_name to examine a variable. You can type list
to see the code around the place the debugger is looking at the time.

At that same prompt you typed run at before you can also type:

break function_name

or

break line_number

Where function_name is the name of one of your functions, or line_number where that is a line number in your source code.

Then type run and the debugger will stop each time you hit that line number or call that function.

Type:

cont

or

step

to keep running from a break point. Step goes one line at a time, while cont just takes off running again.

Hope this helps.

Hi BuckRogers!

Well, we tried running your idea, but we kept getting this:

```/usr/bin/ld: cannot find -lgcc_s
collect2: ld returned 1 exit status
```

We run g-plus-plus as our compiler, not g c c. So I'm personally a little confused as to the instruction about "the number flag from the gcc line."

#7 baavgai

• Dreaming Coder

Reputation: 7361
• Posts: 15,284
• Joined: 16-October 07

Re: Segmentation Fault...and we have no clue why

Posted 25 January 2009 - 01:08 PM

```Record Number: 1
Forename: John	Smith	Sales	555-1234
Surname: Mary	Jones	Wages	555-9876
Department: Paul	Harris	Accts	555-4321
Telephone:

```

Your example file has no tabs. So getline( reader, tab[ i++ ], '\t' ); just reads to the end and slurps up the whole thing. I like to use "~" as a delimiter, since the character is nonsensical on it's own, visible, and unlikely to be data.

While debuggers are ideal, you can do a lot in just your code to tell you what's going on.

Try this:
```while( ! reader.eof() ) {
if ( ( i + 1 ) % 4 == 0 )
else
cout << "read " << i << ":\t" << tab[i] << endl;
i++;
}

```

You should get 0..11, yes? I bet you get 0..2. Put tabs in your file, or change the delimiter, and see how it goes.

#8 bytescribe

Reputation: 0
• Posts: 19
• Joined: 17-January 09

Re: Segmentation Fault...and we have no clue why

Posted 25 January 2009 - 01:50 PM

baavgai, on 25 Jan, 2009 - 12:08 PM, said:

```Record Number: 1
Forename: John	Smith	Sales	555-1234
Surname: Mary	Jones	Wages	555-9876
Department: Paul	Harris	Accts	555-4321
Telephone:

```

Your example file has no tabs. So getline( reader, tab[ i++ ], '\t' ); just reads to the end and slurps up the whole thing. I like to use "~" as a delimiter, since the character is nonsensical on it's own, visible, and unlikely to be data.

While debuggers are ideal, you can do a lot in just your code to tell you what's going on.

Try this:
```while( ! reader.eof() ) {
if ( ( i + 1 ) % 4 == 0 )
else
cout << "read " << i << ":\t" << tab[i] << endl;
i++;
}

```

You should get 0..11, yes? I bet you get 0..2. Put tabs in your file, or change the delimiter, and see how it goes.

baavgai--

Thanks for the little tip. We tried your idea and we got this result but still with a seg. fault no core dump:

```read 0:	John
Segmentation fault

```

While the book we're using is good, overall, you guys' answers make me wonder about where the author is coming from.

A note, though: the author is writing for those who are using Windows, not Linux. He says that the exercises should work in Linux, but so far, one has not.

#9 baavgai

• Dreaming Coder

Reputation: 7361
• Posts: 15,284
• Joined: 16-October 07

Re: Segmentation Fault...and we have no clue why

Posted 25 January 2009 - 03:18 PM

Right, I gave this one a spin with your original code. This will work if, and only if, your data file is three lines only and tab delimited. If you put a line feed after the third line, making a fourth line, you will crash as you read past the end of your array.

You can avoid this by putting an extra check into your while. e.g.
```	while( i<RANGE && !reader.eof() ) {
getline( reader, tab[i], (( i + 1 ) % 4 == 0) ? '\n' : '\t' );
i++;
}

```

If this code is yours, it's fine; you're learning.

However, if this comes for a book or something claiming to teach the basics of programming, it's not teaching you any good habits. Here's an example of how what you're doing might look in C++.

```#include <fstream>
#include <string>
#include <iostream>
#include <sstream>
#include <vector>

using namespace std;

typedef struct RecordStruct {
string forename;
string surname;
string dept;
string phone;
} RecordType;

typedef vector<RecordType> RecordCollection;

void show(RecordType &rec) {
cout << "Forename: " << rec.forename << endl;
cout << "Surname: " << rec.surname << endl;
cout << "Department: " << rec.dept << endl;
cout << "Telephone: " << rec.phone << endl;
}

void show(RecordCollection &rc) {
int recNum = 0;
RecordCollection::iterator it = rc.begin();
for(;it!=rc.end(); ++it) {
cout << endl << "record: " << ++recNum << endl;
show(*it);
}
}

RecordType parseRecord(string &data) {
static char delim = '\t';
RecordType rec;

stringstream ss(data);
getline(ss, rec.forename, delim);
if (!getline(ss, rec.surname, delim)) { return rec; }
if (!getline(ss, rec.dept, delim)) { return rec; }
getline(ss, rec.phone, delim);
return rec;
}

void loadRecordCollection(const char *fileName, RecordCollection &rc) {
cout << "Error opening input file" << endl;
return;
}

string line;
RecordType rec = parseRecord(line);
if (rec.forename.length() > 0) {
rc.push_back( parseRecord(line) );
}
}
}

int main() {
RecordCollection rc;