Why is this function segfaulting?

  • (2 Pages)
  • +
  • 1
  • 2

21 Replies - 999 Views - Last Post: 04 December 2010 - 08:01 PM Rate Topic: -----

#1 lunixer  Icon User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 120
  • Joined: 29-January 10

Why is this function segfaulting?

Posted 03 December 2010 - 07:40 PM

Hello. The function in question is this:


const Set Set::operator+(const Set& rhs) const
{
	Set result;
	int i=0, j=0;
    cout << "A1" << endl; //Delete this line
	while ((i < numElements) && (j < rhs.numElements))
	{
	    cout << "A2" << endl; //Delete this line
		Multinumber* toadd=new Multinumber;
		cout << "A3" << endl; //Delete this line
		toadd=*(setArray[i]) + *(rhs.setArray[j]); //Segfaulting at this line XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
		cout << "A4" << endl; //Delete this line
		cout << toadd; //Delte this lien
		result.addElement(toadd);
		i++;
		j++;
	}



Obviously the couts that I have included are for testing. The output of the program gets up to where I couted A3 and then terminates. A3 never loops or prints again, so it is definitely not because the setArray variables are going out of bounds. Both of those setArray arrays hold pointers to Multinumbers, which is why I have dereferenced them.

The operator+ function that is being called at this point is this:

Complex* Complex::operator+(const Complex& rhs) const
{
    cout << "CA1" << endl;
    Complex* toreturn=new Complex;
    cout << "CA2" << endl;
	*toreturn = Complex(real+rhs.real,imag+rhs.imag);
    return toreturn;
}



With more couts for testing. Neither of the couts above ever display. I can't figure out why this is segfaulting. Any help would be great. Thank you.

Is This A Good Question/Topic? 0
  • +

Replies To: Why is this function segfaulting?

#2 KYA  Icon User is offline

  • g++ jameson.cpp -o beverage
  • member icon

Reputation: 3093
  • View blog
  • Posts: 19,139
  • Joined: 14-September 07

Re: Why is this function segfaulting?

Posted 03 December 2010 - 07:42 PM

Can I see the class declaration please?
Was This Post Helpful? 0
  • +
  • -

#3 lunixer  Icon User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 120
  • Joined: 29-January 10

Re: Why is this function segfaulting?

Posted 03 December 2010 - 07:45 PM

View PostKYA, on 03 December 2010 - 08:42 PM, said:

Can I see the class declaration please?


Gladly.

Set:


using namespace std;

class Set
{
	private:
		int numElements; //number of elements in the set
		int capacity; //current capacity of the set
        //Preconditions: set with array size greater than 0
        //Postconditions: size of array doubled
		void resize();
		Multinumber** setArray; //array of elements in the set
	public:
        //Preconditions: none
        //Postconditions: creates a blank set
		Set();
        //Preconditions: array of multinumbers, integer that specifies size of array
        //Postconditions: creates a set of multinumbers
		Set(Multinumber* [], int);
        //Preconditions: copy constructor, another set
        //Postconditions: creates a duplicate of the set
		Set (const Set &);
        //Preconditions: two sets with the same Multinumber type (Complex, Rational, Pair)
        //Postconditions: adds two sets, fails if not of same type
		const Set operator+ (const Set&) const;
        //Preconditions: two sets with the same Multinumber type
        //Postconditions: Creates a set with all of the elements of both, fails if not of same type
		const Set setUnion (const Set&) const;
        //Preconditions: two sets
        //Postconditions:Sets one set equal to the other set
		Set& operator= (const Set&);
        //Preconditions: set, Multinumber
        //Postconditions: tests if multinumber exists in set, returns true or false
		bool isMember (Multinumber*) const;
        //Preconditions: instantiated set, element
        //Postconditions: adds element to set
		bool addElement (Multinumber*);
        //Preconditions: instantiated set.
        //Postconditions: returns true if set has no elements, false otherwise
		bool isEmpty();
        //Preconditions: instantiated set
        //Postconditions: returns true if array needs to be resized, false otherwise
		bool isFull();
        //Preconditions: set with more than one element
        //Postconditions: prints object2string of each member of set
		friend ostream& operator << (ostream&, const Set &);
		//friend istream& operator >> (istream&, Set &);
		// set destructor
		~Set();
};

#endif



The virtual class of what is being added:

using namespace std;

class Multinumber
{
public:
    //Preconditions: two multinumbers to add
    //Postconditions: added together based on definition in subclass
	virtual Multinumber* operator+(Multinumber&);
    //Preconditions: one multinumber to set equal to another, same memory allocation
    //Postconditions: multinumber set equal to ther other
	virtual Multinumber& operator=(Multinumber&);
    //Preconditions: two multinumbers to compare
    //Postconditions: bool returned that says whether multinumbers are equivalent as defined by programmer
	virtual bool operator==(Multinumber&);
    //Preconditions: none
    //Postconditions: string written out that defines important information about object, as defined by programmer, replaces <<
	virtual string object2string();
    //Preconditions: already created multinumber object
    //Postconditions: calls appropriate constructor again to redefine object with new numbers, replaces >>
	virtual void makeobject();
    //Destructor
    virtual ~Multinumber();


};

#endif



The inherited class:

#if ! defined (COMPLEX_H)
#define COMPLEX_H

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

using namespace std;

class Complex : public Multinumber
{
 private:
    double real;
    double imag;

 public:
    //Preconditions: none
    //Postconditions: constructor, first variable becomes 'real,' second variable 'imag'
    Complex (double x=0.0, double y = 0.0);
    //Preconditions: two multinumbers to add
    //Postconditions: added together, fails if not of complex type
    Complex* operator+(const Complex&) const;
	//Preconditions: two multinumbers to compare
    //Postconditions: bool returned that says whether multinumbers are equivalent, fails if not complex type
	bool operator==(const Complex&) const;
    //Preconditions: one complex to set equal to another, same memory allocation
    //Postconditions: complex set equal to ther other, fails if multinumber is not complex
	const Complex& operator=(const Complex&);
 	//Preconditions: none
    //Postconditions: string written out that defines important information about object, as defined by programmer, replaces <<
	string object2string();
  	//Preconditions: already created complex object
    //Postconditions: calls appropriate constructor again to redefine object with new numbers, replaces >>
	void makeobject();
	//Destructor
	~Complex();

};

#endif  // COMPLEX_H


Was This Post Helpful? 0
  • +
  • -

#4 r.stiltskin  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1833
  • View blog
  • Posts: 4,927
  • Joined: 27-December 05

Re: Why is this function segfaulting?

Posted 03 December 2010 - 07:56 PM

Did you deal with both issues that I pointed out in your previous thread here?

Have you tried printing those SetArray elements that you are trying to add? That would be a first step to verify that they actually exist. The segfault suggests to me that they don't.
Was This Post Helpful? 1
  • +
  • -

#5 KYA  Icon User is offline

  • g++ jameson.cpp -o beverage
  • member icon

Reputation: 3093
  • View blog
  • Posts: 19,139
  • Joined: 14-September 07

Re: Why is this function segfaulting?

Posted 03 December 2010 - 08:07 PM

Can you show me where you initialize the Multinumber** array for the Set instance?
Was This Post Helpful? 1
  • +
  • -

#6 lunixer  Icon User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 120
  • Joined: 29-January 10

Re: Why is this function segfaulting?

Posted 03 December 2010 - 08:08 PM

View Postr.stiltskin, on 03 December 2010 - 08:56 PM, said:

Did you deal with both issues that I pointed out in your previous thread here?

Have you tried printing those SetArray elements that you are trying to add? That would be a first step to verify that they actually exist. The segfault suggests to me that they don't.


I have fixed that. And I just tried to print the lhs of that statement and it seems that there is nothing. I got another segfault. But I don't understand why that is.

View PostKYA, on 03 December 2010 - 09:07 PM, said:

Can you show me where you initialize the Multinumber** array for the Set instance?

Various constructors:

Set::Set()
{
	capacity = 10;
	numElements = 0;
	setArray = new Multinumber*[capacity];
}

//################################################################################################################

Set::Set(Multinumber* tempArray[], int tempSize)
{
	capacity = tempSize*2;
	setArray = new Multinumber*[capacity];
	for (int i=0; i<tempSize; i++)
	{
	    cout << "in for loop" << endl; //Delete this line
		addElement(tempArray[i]);
	}
}

//################################################################################################################

Set::Set (const Set& rhs) //Copy constructor definitely works
{
	numElements = 0;
	capacity=10;
	setArray=new Multinumber*[capacity];
	for (int i=0; i<rhs.numElements; i++)
	{
	    cout << "In copy constructor for loop" << endl; //Delete this line
		addElement(rhs.setArray[i]);
		cout << "Returned to copy constructor" << endl; //Delete this line
	}
}


Was This Post Helpful? 0
  • +
  • -

#7 KYA  Icon User is offline

  • g++ jameson.cpp -o beverage
  • member icon

Reputation: 3093
  • View blog
  • Posts: 19,139
  • Joined: 14-September 07

Re: Why is this function segfaulting?

Posted 03 December 2010 - 08:12 PM

Unless you're doing it in addElement() I don't see where you are allocating memory/initializing objects for each index of the ** array.

No allocation = no object = no memory = seg fault.
Was This Post Helpful? 1
  • +
  • -

#8 lunixer  Icon User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 120
  • Joined: 29-January 10

Re: Why is this function segfaulting?

Posted 03 December 2010 - 08:20 PM

View PostKYA, on 03 December 2010 - 09:12 PM, said:

Unless you're doing it in addElement() I don't see where you are allocating memory/initializing objects for each index of the ** array.

No allocation = no object = no memory = seg fault.


This is my addElement (This time I took out the test couts). So where would the best place to allocate this memory be? My trouble is that when this is instantiated I don't know whether I should allocate a new Pairs, a new Complex, or a new Rational (subclasses of Multinumber). Is there any way to make a new Multinumber and use that without the possibility of a slicing effect?

bool Set::addElement(Multinumber* newElement)
{
	bool success = false;
	if(isFull())
	{
		resize();
	}
	if(!isMember(newElement))
	{
		setArray[numElements] = newElement;
		numElements++;
		success = true;
	}
	return success;
}


Was This Post Helpful? 0
  • +
  • -

#9 KYA  Icon User is offline

  • g++ jameson.cpp -o beverage
  • member icon

Reputation: 3093
  • View blog
  • Posts: 19,139
  • Joined: 14-September 07

Re: Why is this function segfaulting?

Posted 03 December 2010 - 08:26 PM

The problem is right here:

setArray[numElements] = newElement;



The parameter [newElement] was never allocated.

--
As for the allocation of a derived class:

at what point in the program will it know what type it will need to hold? How will it make that determination? User input? In any case, allocate right before you need it.


If that isn't possible, do a null pointer check if a function or operator is attempted on an object whose data is uninitialized.
Was This Post Helpful? 1
  • +
  • -

#10 lunixer  Icon User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 120
  • Joined: 29-January 10

Re: Why is this function segfaulting?

Posted 03 December 2010 - 08:39 PM

View PostKYA, on 03 December 2010 - 09:26 PM, said:

If that isn't possible, do a null pointer check if a function or operator is attempted on an object whose data is uninitialized.


What do you mean by this? Sounds promising.

The problem is that I never really know what type will be made. The set is polymorphic and type agnostic. I can't allocate in the operator+ method because the set can hold all three types. I can't allocate in the driver because then I would have to pass all of the allocated variables into the operator+ method but I don't know how many are in the set. And I also can't allocate in the addElement() function because I don't know what the type is. So I somehow have to figure out how to allocate three times, test which type is correct, and then delete the other two. But I can't use == because of the slicing effect. Is there any other way to do this?

EDIT: Other elements that I add to the set work because I know what type they are when they are created. They are either hardcoded or the user chooses from a menu of types and creates one, in which case I can allocate at that point. The problem is just with these virtual functions (+,=,etc) that can be any type.

This post has been edited by lunixer: 03 December 2010 - 08:42 PM

Was This Post Helpful? 0
  • +
  • -

#11 lunixer  Icon User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 120
  • Joined: 29-January 10

Re: Why is this function segfaulting?

Posted 03 December 2010 - 09:18 PM

EDIT: Broke a lot of stuff by doing this.

This post has been edited by lunixer: 03 December 2010 - 09:41 PM

Was This Post Helpful? 0
  • +
  • -

#12 KYA  Icon User is offline

  • g++ jameson.cpp -o beverage
  • member icon

Reputation: 3093
  • View blog
  • Posts: 19,139
  • Joined: 14-September 07

Re: Why is this function segfaulting?

Posted 04 December 2010 - 06:18 AM

View Postlunixer, on 03 December 2010 - 08:39 PM, said:

So I somehow have to figure out how to allocate three times, test which type is correct, and then delete the other two.



This is indicative of a bad design.

Polymorphism allows you to use a pointer to the base class, allocate a derived class and have the proper functions/data used at run-time. There has to be some determining criteria that dictates which type is to be made. Where is that located in your program code?
Was This Post Helpful? 0
  • +
  • -

#13 lunixer  Icon User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 120
  • Joined: 29-January 10

Re: Why is this function segfaulting?

Posted 04 December 2010 - 07:08 AM

View PostKYA, on 04 December 2010 - 07:18 AM, said:

View Postlunixer, on 03 December 2010 - 08:39 PM, said:

So I somehow have to figure out how to allocate three times, test which type is correct, and then delete the other two.



This is indicative of a bad design.

Polymorphism allows you to use a pointer to the base class, allocate a derived class and have the proper functions/data used at run-time. There has to be some determining criteria that dictates which type is to be made. Where is that located in your program code?


Well I suppose it is in the operator overload. But I am not certain that my code is calling the correct overload every time. It might be calling the base class, based on some couts I have done. I don't understand why that would be given that I am using pointers. For example, when I tried to solve my problem with the addElement like this, it stopped segfaulting entirely, but also refused to print anything, which seems to me like it was calling only the functions in Multinumber. I am going to attach my code in case you are interested in taking a look. Thanks!
Multinumber* jack=new Multinumber;
*jack=*newElement //newElement is the unallocated parameter of the function where I put this 

Attached File(s)

  • Attached File  code.zip (8.78K)
    Number of downloads: 33

Was This Post Helpful? 0
  • +
  • -

#14 KYA  Icon User is offline

  • g++ jameson.cpp -o beverage
  • member icon

Reputation: 3093
  • View blog
  • Posts: 19,139
  • Joined: 14-September 07

Re: Why is this function segfaulting?

Posted 04 December 2010 - 08:29 AM

newElement [the parameter to your operator overload] still isn't initialized/allocated to anything, so you're still assigning a null pointer. Not to mention the memory leaks all over the place.


Show me exactly where the program determines which derived class to instantiate. Until I see how, we're paddling in circles here.
Was This Post Helpful? 0
  • +
  • -

#15 lunixer  Icon User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 120
  • Joined: 29-January 10

Re: Why is this function segfaulting?

Posted 04 December 2010 - 08:53 AM

View PostKYA, on 04 December 2010 - 09:29 AM, said:

newElement [the parameter to your operator overload] still isn't initialized/allocated to anything, so you're still assigning a null pointer. Not to mention the memory leaks all over the place.


Show me exactly where the program determines which derived class to instantiate. Until I see how, we're paddling in circles here.


Thanks for your help. I'll fix those memory leaks once I get this thing working. Anyway, part of the decision what to instantiate is made in the driver.

BTW, should these be Multinumber* c1=new Complex(x,x)?


int main()
{
    Set seta,setc,setd,sete,setf;
    Complex* c1=new Complex(6,4);
    Complex* c2=new Complex(5,6);
    Complex* c3=new Complex(8,-1);
    Complex* c4=new Complex(7,6);
    Complex* c5=new Complex(11,22);
    Pairs* p1=new Pairs(2,3);
    Pairs* p2=new Pairs(8,1);
    Pairs* p3=new Pairs(7,77);
    Pairs* p4=new Pairs(1,1);
    Pairs* p5=new Pairs(-1,10);
    Rational* r1=new Rational(8,88);
    Rational* r2=new Rational(1,2);
    Rational* r3=new Rational(11,9);
    Rational* r4=new Rational(12,5);
    Rational* r5=new Rational(11,6);
    seta.addElement(c1);
    seta.addElement(c2);
    seta.addElement(c3);
    cout <<"First set:" << endl;
    cout << seta;
    cout << "Test isfull (initial capacity 10): ";
    cout << seta.isFull() << endl;
    cout << "Making second set with array." << endl;
    Multinumber* carr[2];
    carr[0]=c4;
    carr[1]=c5;
    Set setb(carr,2);
    cout << "Second set:" << endl;
    cout << setb;
    cout << "Testing union of two sets and equals operator overload:" << endl;
    setc = seta.setUnion(setb);
    cout << setc << endl;
    cout << "Testing addition" << endl;
    setd = seta+setb;
    cout << setd << endl;
    cout << "Creating a set with pairs:" << endl;
    sete.addElement(p1);
    sete.addElement(p2);
    sete.addElement(p3);
    cout << sete;
    cout << "Creating a set with rationals:" << endl;
    setf.addElement(r1);
    setf.addElement(r2);
    setf.addElement(r3);
    cout << setf << endl;
    cout << "Adding to itself." << endl;
    Set setg =setf + setf;
    cout << setg << endl;
    cout << "End of program. Thanks for watching!";
}



Each of the subclasses knows what it is (if the subclass functions are called rather than the superclass).


#include "Complex.h"
#include<sstream>
#include "Multinumber.h"

using namespace std;

void Complex::makeobject()
{
    cout << "Please enter two decimal values. The first is the real and the second is the imaginary." << endl;
    cin >> real;
    cin >> imag;
    cout << "Result: ";
    cout << object2string() << endl;
}

//################################################################################################################

Complex::Complex (double x, double y)
{
    real = x;
    imag = y;
}

//################################################################################################################

Complex* Complex::operator+(const Complex& rhs) const
{
    Complex* toreturn=new Complex;
	*toreturn = Complex(real+rhs.real,imag+rhs.imag);
    return toreturn;
}

//################################################################################################################

bool Complex::operator==(const Complex& rhs) const
{
    return ((real == rhs.real) && (imag == rhs.imag));
}

//################################################################################################################

const Complex* Complex::operator=(const Complex& rhs)
{
    imag=rhs.imag;
    real=rhs.real;
    Complex* toreturn=new Complex;
    toreturn=this;
    return toreturn;
}

//################################################################################################################

string Complex::object2string()
{
	ostringstream os;
	if ((real != 0) || (imag == 0))
		os << real;
	if (imag != 0)
	{
		if (imag != 1)
			if (imag > 0)
				os << "+";
		os << imag;
		os << "i";
	}
	return os.str();
}

//################################################################################################################

Complex::~Complex()
{
}



So I guess it would be one of those two. But a decent portion of my problem is that it seems that the superclass functions are being called, even though I have them set up as pointers to the superclass, with subclass objects. Once again, thank you very much for your help.

This post has been edited by lunixer: 04 December 2010 - 08:54 AM

Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2