Problem with chained overloaded operator

OS: Ubuntu Linux 9.4
GCC: v4.4.1

I'm writing a String class while learning about operator overloading. I'm having trouble with how to use overloaded binary operators in chained expressions. In this case, I have a String class whose private data members are char *str and int length. I wrote an overloaded + operator like this that employs a conversion constructor specifying member length:

1
2
3
4
5
6
7
8
String String::operator+( const String &s )
{
	String temp( length + s.length );
	strcpy( temp.str, str );
	strcat( temp.str, s.str );

	return temp;
}


In my driver program, I tried this test:

1
2
3
4
String str( "first," );
String str1( " second," );
str.operator+=((str1.operator+(" third,")).operator+(" fourth and final!"));
cout << "\nTesting String concatenation operator\n" << str.print() << "\n\n";


I wrote the operator statement using function notation just to see if I understand it properly, the resulting output is the same as using

str += str1 + " third" + " fourth and final!";

The output is (abridged):

1
2
3
4
Testing String concatenation operator
first, second, third fourth an1

*** glibc detected *** ./string: free(): invalid next size (fast): 0x00000000023340d0 ***


with a backtrace and memory map dump. The += operator doesn't appear to be the problem, I tried the driver operator statement using my overloaded assignment operator and had the same output. There seems to be a buffer overflow, so possibly my error lies in my not handling dynamic memory properly and resizing the str data.

My question is, am I approaching this the right way or is there some flaw in my understanding of how to build a chained statement like I attempted? I'm thinking this has something to do with my returning a String object by value from the operator+() function, and when a temporary local object is created in the statement and chained with the next part of the expression, it isn't resizing the str array.

I wanted to return a const reference from operator+(), but I couldn't see how to avoid a memory leak since the returned handle in the expression in question would cease to exist after the statement ended, and burdening the client code with deleting an object in this manner is bad design anyways. Help me clarify my thinking here!

If this helps, here's how I handled the operator+=() function.
1
2
3
4
5
6
7
8
9
10
11
12
void String::operator+=( const String &s )
{
	length += s.length;
	char *temp = new char[length + 1];
	if( temp == 0 )
		exit(1);
	strcpy( temp, str );
	strcat( temp, s.str );
	delete [] str;
	str = allocate( temp );
	delete [] temp;
}

/facepalm

I just realized I was thinking my conversion constructor set aside length + 1 characters on the heap for the str pointer. I was mistaken.

1
2
3
4
5
6
7
8
9
String String::operator+( const String &s )
{
	String temp( length + s.length );
	temp.str = new char[temp.length + 1];
	strcpy( temp.str, str );
	strcat( temp.str, s.str );

	return temp;
}


did the trick. I'm still curious as to how I could avoid returning the temp object by value and work the operator+() function so that it returned a reference to a String object without running into a memory leak.

Here's my conversion constructor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
String::String( int len /*= 0*/ )
{
	length = len;
	str = allocate("");
}


char *  String::allocate( const char *s )
{
	char *cptr = new char[strlen(s) + 1];
// I'm now going to use char *cpt = new char[length + 1];
	if( cptr == 0 )
		exit(1);
	strcpy( cptr, s );

	return cptr;
}
Last edited on
Topic archived. No new replies allowed.