Segmentation fault (core dumped) error

Hi. Im trying to write a code that will process grade data from a file. The program compiles but when i try to run it I get the error "segmentation fault
(core dump)" I know this error is related to memory but I dont know how to tell whats causing it. Is there a way to know?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
  #include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include "student.h"
#include "bubble.h"
using namespace std;

//Name and class
struct classStats{
float mean;
float min;
float max;
float medium;
char *name;
}; 
int main(){
string userInput;
int sum;
int min;
int max;
classStats stats;
student_info **student = NULL;
student = new student_info *[19]; //allocates memory for char pointers declared in structs

while(cin >> userInput){ //continues while cin reads something
for (int i=0; i < 19; i++){ //keep reading the input and write it to the correct variable from the struct
cin >> student[i]->first;
cin >> student[i]->last;
cin >> student[i]->exam1;
cin >> student[i]->exam2;
cin >> student[i]->exam3;
//calculate the average of student i
sum  = student[i]->exam1 + student[i]->exam2 + student[i]->exam3;
student[i]->mean = sum / 3;
}
min, max = 0;
//find the min/max of all the grades
for (int i=0; i < 19; i++){
	if (min > student[i]->exam1 || min > student[i]->exam2 || min > student[i]->exam3) //if the current min is bigger than either exam 1 2 or 3 set that exam as the min
	{ if (student[i]->exam1 < student[i]->exam2 && student[i]->exam3){ //if exam 1 is less than exam 2 or 3 then it is the min
		min = student[i]->exam1;
		}
	if (student[i]->exam2 < student[i]->exam1 && student[i]->exam3){
		min = student[i]->exam2;
			}
	if (student[i]->exam3 < student[i]->exam1 && student[i]->exam2){
		min = student[i]->exam3;
		}
	}
	 if (max < student[i]->exam1 || min > student[i]->exam2 || min > student[i]->exam3) //if the current max is smaller than either exam 1 2 or 3 set that exam as the max
        { if (student[i]->exam1 > student[i]->exam2 && student[i]->exam3){ //if exam 1 is greater than exam 2 or 3 then it is the ax
                max = student[i]->exam1;
                }
        if (student[i]->exam2 > student[i]->exam1 && student[i]->exam3){
                max = student[i]->exam2;
                }
        if (student[i]->exam3 > student[i]->exam1 && student[i]->exam2){
                max = student[i]->exam3;
                } 
       }
}
stats.min = min;
stats.max = max;
for (int j=0; j < 19; j++){
cout << student[j]->first << "   " << student[j]->last << "   " << student[j]->mean << endl;
}
delete []  student;
}
return 0;
} 

> Is there a way to know?
run your program through a debugger
also, valgrind will tell you about invalid access, uninitialised variables, double deletes and more.
Your probably trying to process something that doesn't exist.
are you checking for empty lines, end of file ?

Another way to tell is put in debug statements.
Im checking for the end of the file
Hello ObiNation00,

"<stdio.h>" is not needed because you have no C code that uses it. And "iostream" will cover all the C++ code that you have written an that I can see.

"<stdlib.h>" is 50/50 you do not really need it because I believe somewhere in "iostream" it is includeed, but it is OK if you leave it in.

You are missing the header file "<string>" in your includes.

And you say that you read from a file. You will need to include "<fstream>".

Line 8 refers to a class, but you define a struct. Kind of miss-leading.

Unless you are stuck using "float"s, "double"s are a better choice.

Your program includes two header files that you wrote, but you did not include them. This along with the input makes it hard for anyone to test your program. Since they are part of the program include them with your code.

cin >> student[i]->first;. This may work, but I more often see and have used cin >> student[i].first;.

One last point: Watch your indenting. It make the code easier to read and follow. Also a few blank lines will break up the ode and make it easier to read also.

Having to create your two header file with no idea what they might contain will take longer to get the program to a point to test.

As far as your "segmentation fault" goes all I can think of right now is that "student[i]" may be going past the end of the array.

Another possibility. Line 22 creates a pointer to a pointer, i.e., a 2D array, but line 23 only creates memory for one of the pointers, i.e., the first dimension of the array.

Some thoughts for now. I will dig into the program tomorrow with a fresh mind.

Hope that helps,

Andy
sorry about forgetting the header files
bubble.h is
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void bubble(student *array[], int size)
{
  int x;
  int y;
  student *temp = NULL;

  for(x = 0; x < size; x++) {
    for(y = 0; y < size-1; y++) {
      if(array[y]->mean > array[y+1]->mean) {
        temp = array[y+1];
        array[y+1] = array[y];
        array[y] = temp;
      }
    }
  }

  return;
}


and student.h is
1
2
3
4
5
6
7
8
typedef struct student_info {
  char  *first;
  char  *last;
  int   exam1;
  int   exam2;
  int   exam3;
  float mean;
} student;


as for line 8 that was just a reminder for me to put my name in later for when I submit it
$ g++ foo.cpp -ggdb -W{all,extra,pedantic}
foo.cpp: In function ‘int main()’:
foo.cpp:36: warning: left operand of comma operator has no effect [-Wunused-value]
min, max = 0;

$ gdb ./a.out
(gdb) run
asdf #this is user input
Program received signal SIGSEGV, Segmentation fault.
main () at foo.cpp:27
27				cin >> student[i]->first;
(gdb) print i
$1 = 0
(gdb) print student[i]
$2 = (student_info *) 0x0
(gdb) quit

$ valgrind ./a.out
==31111== Use of uninitialised value of size 8
==31111==    at 0x1093AA: main (foo.cpp:27)
==31111== 
==31111== Invalid read of size 8
==31111==    at 0x1093AA: main (foo.cpp:27)
==31111==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==31111== 
==31111== 
==31111== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==31111==  Access not within mapped region at address 0x0
==31111==    at 0x1093AA: main (foo.cpp:27)



student = new student_info *[19]; reserve memory for the pointers, but those pointers are invalid
so you'll need to do something like student[i] = new student;
but that's too complicated, ¿why not simply student_info student[19];?

then you need to reserve for student[i].first and student[i].last...
use std::string, dammit
Last edited on
Hello ObiNation00,

I found that your use of pointers to be the biggest problem. The question is are you required to use pointers for your program?

In the struct "student_info", you may consider "StudentInfo" The capital "S" will let you know that it is a class, function or struct, you have char *first;, but in "main" you have cin >> student[i]->first; which leads one to believe that a letter is expected, but char *first; is expecting an address not a letter. When I removed the asterisk form char *first; and changed cin >> student[i]->first; to cin >> student[i].first; it worked. If you have to use pointers it can be fixed, but it will take more work.

In the following code look for the comments I have made:

main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <iostream>
#include <string>
//#include <stdio.h>
//#include <stdlib.h>
#include "student.h"
#include "bubble.h"

using namespace std;

constexpr std::size_t MAXSIZE{ 3 };
constexpr std::size_t MAXARRAYSIZE{ 19 };

//Name and class
struct classStats
{
	float mean;
	float min;
	float max;
	float medium;
	char *name;
};

int main()
{
	string userInput;
	float sum{};  // <--- Changed from "int' to "float"
	float min{};
	float max{};
	classStats stats;
	student_info student[MAXARRAYSIZE];

	//student = new student_info *[19]; //allocates memory for char pointers declared in structs

	while (cin >> userInput)
	{ //continues while cin reads something
		for (int i = 0; i < MAXSIZE; i++) { //keep reading the input and write it to the correct variable from the struct
			std::cout << "\n Enter first initial: ";
			cin >> student[i].first;
			std::cout << "\n Enter last initial: ";
			cin >> student[i].last;
			std::cout << "\n Enter first exam grade: ";
			cin >> student[i].exam1;
			std::cout << "\n Enter second exam grade: ";
			cin >> student[i].exam2;
			std::cout << "\n Enter third exam grade: ";
			cin >> student[i].exam3;

			//calculate the average of student i
			sum = static_cast<float>(student[i].exam1) + static_cast<float>(student[i].exam2) + static_cast<float>(student[i].exam3);
			student[i].mean = sum / static_cast<float>(3.0); // <--- Changed to 3.0
		}

		min = max = 0;  // <--- Changed. Using the "," operator only set "max" to zero.

		//find the min/max of all the grades
		for (int i = 0; i < MAXSIZE; i++)
		{
			if (min > student[i].exam1 || min > student[i].exam2 || min > student[i].exam3) //if the current min is bigger than either exam 1 2 or 3 set that exam as the min
			{
				if (student[i].exam1 < student[i].exam2 && student[i].exam3)
				{ //if exam 1 is less than exam 2 or 3 then it is the min
					min = static_cast<float>(student[i].exam1);
				}
				if (student[i].exam2 < student[i].exam1 && student[i].exam3)
				{
					min = static_cast<float>(student[i].exam2);
				}
				if (student[i].exam3 < student[i].exam1 && student[i].exam2)
				{
					min = static_cast<float>(student[i].exam3);
				}
			}
			if (max < student[i].exam1 || min > student[i].exam2 || min > student[i].exam3) //if the current max is smaller than either exam 1 2 or 3 set that exam as the max
			{
				if (student[i].exam1 > student[i].exam2 && student[i].exam3)
				{ //if exam 1 is greater than exam 2 or 3 then it is the ax
					max = static_cast<float>(student[i].exam1);
				}
				if (student[i].exam2 > student[i].exam1 && student[i].exam3)
				{
					max = static_cast<float>(student[i].exam2);
				}
				if (student[i].exam3 > student[i].exam1 && student[i].exam2)
				{
					max = static_cast<float>(student[i].exam3);
				}
			}
		}

		stats.min = min;
		stats.max = max;

		for (int j = 0; j < 19; j++)
		{
			cout << student[j].first << "   " << student[j].last << "   " << student[j].mean << endl;
		}
		delete[]  student;
	}
	return 0;
}


student.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#ifndef _STUDENT_   // <--- Added include guard.
#define _STUDENT_

typedef struct student_info
{
	char  first;
	char  last;
	int   exam1;  // <--- Should be made a "double" or at least a "float"
	int   exam2;
	int   exam3;
	float mean;
};// student;  // <--- Turns out that this is not really needed here, but could still be used.

#endif // end !_STUDENT_ 


bubble.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#ifndef _BUBBLE_	 
#define _BUBBLE_
void bubble(student_info array[], int size)
{
	int x;
	int y;
	student_info temp;

	for (x = 0; x < size; x++)
	{
		for (y = 0; y < size - 1; y++)
		{
			if (array[y].mean > array[y + 1].mean)
			{
				temp = array[y + 1];
				array[y + 1] = array[y];
				array[y] = temp;
			}
		}
	}

	return;
}

#endif // end !_BUBBLE_ 

Notice the changes that were made to make it work. At least it accepts input. I have not tested it fully.

The while loop in "main" line 34 is not the best way to do the while condition. The while condition is waiting for input before the for loop can be executed. The problem you have no idea that you need to enter something to continue. You could try while (true) to create an endless loop and use break to break out of the while loop.

If you do not know about it yet the #ifndef _STUDENT_ and other "#something" is called an include guard. This is a good thing to learn to minimize problems.

If you have instructions for this problem it would help if you would post them. This way answers can be better tailered to your problems.

Hope that helps,

Andy
Topic archived. No new replies allowed.