Segementation fault from passing string

I am trying to make a simple demographics input program. Enter name, age, birthdate, out put to a CSV file. I am getting a segmentation fault when my getName method finishes in a loop. So I can enter the names until the for loop in main finishes and then it gets a segmentation fault. I know it has something to do with strings being passed between the functions because if I change the string to int in the function it works just fine. I'm pretty sure it has something to do with memory allocation after the strings get deleted at the end of the loop. If I declare first_name and last_name in the driver page and not the header file it works fine. I'm just not sure of a fix, any help is appreciated. Code is below
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
Main

#include <iostream>
#include "People.h"

using namespace std;
void demographics();

int main()
{
    demographics();

    return 0;
}

void demographics()
{
    short elements = 1;
    PersonalData person[elements];
    short choice;
    int data;

     for(int i =0; i<=elements; i++)
    {
        string name, name2;
        cout << "Please enter first name for child " << i+1 << endl;
        cin >> name;

        cout << name << "'s last name: ";
        cin >> name2;
        person[i].setName(name, name2);
    }
    return;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
people.h

#ifndef PEOPLE_H_INCLUDED
#define PEOPLE_H_INCLUDED
#include <iostream>

using namespace std;

class PersonalData
{
    private:
        string  first_name = "place holder";
        string  last_name = "place holder";

    public:
        void setName(string, string);
};


1
2
3
4
5
6
7
8
9
10
11
12
13
14
people.cpp

#include "People.h"
#include <iostream>

using namespace std;

void PersonalData::setName(string  f_name,  string  l_name)
{
    first_name = f_name;
    last_name = l_name;

}
Last edited on
It looks you never even included the string header in any of your files? #include <string>
That shouldn't cause a segmentation fault, as its a memory allocation issue. I did add the string header just to make sure but, it did not help. Thanks though.
Here this works.

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
#include <iostream>
#include <string>
using namespace std;
void demographics();

class PersonalData
{
private:
	string  first_name = "place holder";
	string  last_name = "place holder";

public:
	void setName(string, string);
	void getName();
};
int main()
{
	char response;
	demographics();

	cin >> response;
	return (0);
}

void demographics()
{
	constexpr short elements = 2;
	PersonalData person[elements];

	for (int i = 0; i < elements; i++)
	{
		string name, name2;
		cout << "Please enter first name for child " << i + 1 << endl;
		cin >> name;

		cout << name << "'s last name: ";
		cin >> name2;
		person[i].setName(name, name2);
	}
	for (int names = 0; names < elements; names++) {
		person[names].getName();
	}
	return;
}
void PersonalData::setName(string  f_name, string  l_name)
{
	first_name = f_name;
	last_name = l_name;

}

void PersonalData::getName()
{
	cout << first_name << ' ' << last_name << '\n';
}
@AgentNoise

I guess you have gathered that an array size must constant and known at compile time. And trying to put 2 things into something that holds 1 thing doesn't work.

Rather than arrays, consider making Name a class of it's own, with a private std::vector<std::string> of the names. That way you can cope with those that have multiple middle names, and it will be a much more general solution.

Always try to use the STL as much as you can, unless you are forbidden by your teacher.

The assignment in this part isn't necessary:

1
2
3
    private:
        string  first_name = "place holder";
        string  last_name = "place holder";


Good Luck !!
I'm actually teaching myself here. I still can not get it to work. I always get the segmentation fault at the end of the for loop. Do I have to retrieve the information immediately after the loop? I was hoping to hold it so more information can be entered and then written to a CSV file. Should I just not enter the name till the end, them immediately write the file before leaving the for loop? That seems kind of hackey.

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
Main

#include <iostream>
#include "People.h"

using namespace std;

void demographics();

int main()
{
    demographics();

    return 0;
}

void demographics()
{
    short elements = 2;
    Names test[elements];

     for(int i =0; i<=elements; i++)
    {
        string name;
        vector<string> name2;
        cout << "Please enter first name for child " << i+1 << endl;
        cin >> name;
        name2.push_back(name);
        test[i].setName(name2);

    }
    return;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
People.h

#ifndef PEOPLE_H_INCLUDED
#define PEOPLE_H_INCLUDED
#include <iostream>
#include <string>
#include <vector>

using namespace std;


class Names
{
    private:
        vector<string> names;
    public:
        void setName(vector<string>&);
};

#endif // PEOPLE_H_INCLUDED 


1
2
3
4
5
6
7
8
9
10
11
12
people.cpp

#include "People.h"
#include <iostream>
#include <string>
using namespace std;

void Names::setName(vector<string>& f_l_name)
{
    names = f_l_name;
}


Part of your problem is in the following snippet:
1
2
3
4
5
   short elements = 2;
    Names test[elements];

     for(int i =0; i<=elements; i++)
    {


In this snippet you try to create an array of Names named test with a size of two. Then you try to access three elements in your loop. When dealing with arrays and loops using operator<= will usually lead to accessing the array one more time than expected.

Also note that using a non-compile time constant to create an array is not allowed in the C++ standard. The first line should be:

1
2
3
4
   const short elements = 2;
   //or
   constexpr short elements = 2;
   // http://en.cppreference.com/w/cpp/language/constexpr 


By the way I really don't understand what you're trying to do in the body of that loop. Perhaps you could describe the logic in English?
@AgentNoise

When you put a class definition into a header file, name the file exactly after the class name, this avoids confusion. I like to name my header files .hpp it means there is c++ code inside. So the Name class goes into Name.hpp and it's corresponding implementation file would be Name.cpp.

The Person class could have a member which is of type Name, and other things like date of birth, address etcetera. These could have their own type as well. Then in main have a std::vector<Person> PeopleDatabase;

Make sure that each class has an interface of functions so you can retrieve the private information from them.

@jlb
By the way I really don't understand what you're trying to do in the body of that loop.


I had suggested that the Name class hold a std::vector<std::string>

But if the OP is going to use a vector<string> for the name then they should also be using a vector<Name> instead of the array.

I asked the OP to explain what he is trying to do in that loop, because the logic appears severely flawed. But perhaps I should have broadened the scope of my question.

What exactly is the purpose of the demographics() function?

@jib

Shortly after posting I had realized the issue with the <= and gotten past the segmentation fault.
I am still a bit confused on vectors. They seem might handy but I am not at all familiar with them. Been on youtube trying to familiarize myself. I am all self taught and still pretty new so demographics() may not be necessary

I would use the demographics function to call the needed methods, getAge, getBirthdate etc, and enter in the corresponding data.

@TheIdeasMan

In the loop I am just asking for the first name and then pushing it to the Names vector string. where the variable name is just a place holder to but pushed to the vector name2 because I could not figure out how to directly cin to the vector name2. I'm pretty sure I am not doing that correct but its the only way I could get it to work.

I think I will be scrapping this to start fresh, get it straight in my head and then change the naming conventions.
I would use the demographics function to call the needed methods, getAge, getBirthdate etc, and enter in the corresponding data.


And what exactly are these needed methods? IMO, at this point you only have a very vague idea as to what you want this function to accomplish. You really should have a firm idea as to what you want to accomplish before you even start to write the program.

Also functions should be your friend. Try to make your functions do as little as possible, many times as little as one thing. Design your functions so that they are easy to test outside your main program.
Last edited on
Topic archived. No new replies allowed.