Overloading preincrement causing abnormal exit.

H

Huck Phin

OK, so I have looked and looked for something similar to my problem,
and I cannot find one. I am writing a program for a HugeInteger, and I
am attempting to overload the preincrement, postincrement,
predecrement, and postdecrement operators. I realize that they are
really all the same, and if I get one of the four operators working, I
can get the rest. I have overloaded all of the other operators such as
+, -, <, >, <=, etc. and there is no issue with that. I have tested my
class to work with a HugeInteger.add( otherHugeInteger ), and it works
fine. My endstate that I am looking for is for my program to print out
the value, and not terminate abnormally.

Here's the code that works for me.

// Preincrement operator
HugeInteger HugeInteger::eek:perator++( int )
{
return *this;
}

As we all know, the preincrement requires that you need to add 1 to the
object, and then return this back. However, I have tried everything
but the right answer with no luck. So try to get my object to add
something, I tried this method.

// Preincrement operator
HugeIntege HugeInteger::eek:perator++( int )
{
HugeInteger one( 1 ); // I have made a constructor to take in an
integer, which works also

cout << "*this: " << *this << endl; // Debug statements

*this = (*this).add( one );

cout << "*this: " << *this << endl; // Debug statements
cout << "testaroo..." << endl; // More debug statements

return *this;
}

When I attempt to run my program, I get the following output:

*this: 111
*this: 112
testaroo...

Then, my program terminates, and I get the following message.
"Unhandled exception at 0x00000000:"
"0xC0000005: Access violation reading location 0x00000000.

The exception that is unhandled is First-Chance Exception, which
I don't quite understand what that is. This is the root of my problem,
and I understand this.

So, what this tells me is that my preincrement works inside the
function,
but I cannot return that value. What can I do to fix this?
From reading other posts, I gather that for some reason my program
is pointing to a null pointer. I don't understand how this can be
considering that when I return *this, I am merely returning my
instance of the HugeInteger.

Anyways, I am stuck, and am requesting some help. Thanks in
advance for the help.
 
M

mlimber

Huck said:
OK, so I have looked and looked for something similar to my problem,
and I cannot find one. I am writing a program for a HugeInteger, and I
am attempting to overload the preincrement, postincrement,
predecrement, and postdecrement operators. I realize that they are
really all the same, and if I get one of the four operators working, I
can get the rest. I have overloaded all of the other operators such as
+, -, <, >, <=, etc. and there is no issue with that. I have tested my
class to work with a HugeInteger.add( otherHugeInteger ), and it works
fine. My endstate that I am looking for is for my program to print out
the value, and not terminate abnormally.

Here's the code that works for me.

// Preincrement operator
HugeInteger HugeInteger::eek:perator++( int )
{
return *this;
}

As we all know, the preincrement requires that you need to add 1 to the
object, and then return this back. However, I have tried everything
but the right answer with no luck. So try to get my object to add
something, I tried this method.

// Preincrement operator
HugeIntege HugeInteger::eek:perator++( int )
{
HugeInteger one( 1 ); // I have made a constructor to take in an
integer, which works also

cout << "*this: " << *this << endl; // Debug statements

*this = (*this).add( one );

This line is suspicious, but we can't really say much without seeing
more code. Read the guidelines for posting code that doesn't work here:

http://parashift.com/c++-faq-lite/how-to-post.html#faq-5.8

The gist is: post a minimal but *complete* sample that we can copy and
paste unchanged to reproduce the problem.
cout << "*this: " << *this << endl; // Debug statements
cout << "testaroo..." << endl; // More debug statements

return *this;
}

When I attempt to run my program, I get the following output:

*this: 111
*this: 112
testaroo...

Then, my program terminates, and I get the following message.
"Unhandled exception at 0x00000000:"
"0xC0000005: Access violation reading location 0x00000000.

The exception that is unhandled is First-Chance Exception, which
I don't quite understand what that is. This is the root of my problem,
and I understand this.

That is what Microsoft does when you dereference a null pointer. What
line does it occur on?
So, what this tells me is that my preincrement works inside the
function,
but I cannot return that value.

Not necessarily. Dereferencing a null (or uninitialized) pointer is
undefined behavior according to the standard, which means *anything*
can happen. It may mean you had some other pointer go wild in a
completely unrelated part of the code.
What can I do to fix this?

Use your debugger to locate the bug, and/or post more code as per FAQ
5.8.
From reading other posts, I gather that for some reason my program
is pointing to a null pointer. I don't understand how this can be
considering that when I return *this, I am merely returning my
instance of the HugeInteger.

What is the value of "this" (i.e., the address it points to) after each
statement in that function?

Cheers! --M
 
H

Huck Phin

Thank you for correcting me on the proper posting procedures. I should
have looked at this prior to posting. I have put in the necessary code
for one to compile and view the error that I am having. I have been
working on a different alternative, and that is to return a void value
from the function, and just change the value of the object from inside
of the function. The same problem occurs, which is weird. I have 3
files for my program. (1) HugeInteger.h for my header file, (2),
HugeInteger.cpp which includes my function definitions, and (3)
TestHugeInteger.cpp, which is my driver program. Thank you again for
your patience and time.

*******************
HugeInteger.h
*******************

#include <iostream>

using std::eek:stream;
using std::istream;

#include <string>

using std::string;

class HugeInteger {

//--- Overloaded stream operators ---//
friend ostream &operator<<( ostream &output, HugeInteger &hugeInt );
friend istream &operator>>( istream &input, HugeInteger &hugeInt );

public:
//--- Constructor Methods ---//
HugeInteger( int startValue );
HugeInteger( HugeInteger &hugeInt );

//--- Overloaded shortcut arithmetic operators ---//
void operator++(); // preincrement operator

//--- Transformer Methods ---//
HugeInteger add( HugeInteger operand2 );
void setElementAt( const int index, const int newElement );

//--- Accessor Methods ---//
string outputInteger();
int getElementAt( int index );

//--- Constant Declarations ---//
static const int NUM_DIGITS = 10;

private:
int numbers[ NUM_DIGITS ];

};


****************************
HugeInteger.cpp
****************************

#include <iostream>
#include "HugeInteger.h"
#include <string>

using std::cout;
using std::endl;

// Copy constructor
HugeInteger::HugeInteger( HugeInteger &otherHugeInt )
{
for ( int i = 0; i < NUM_DIGITS; i++ )
{
numbers[ i ] = otherHugeInt.getElementAt( i );
}

}


// Gets int element at specified index value
int HugeInteger::getElementAt( int index )
{
if ( ( index < 0 ) || ( index > NUM_DIGITS - 1 ) )
{
index = 0;
}

return numbers[ index ];
}

// Constructor method taking int value
HugeInteger::HugeInteger( int startValue )
{
int inputValue = startValue;

for ( int i = 0; i <= NUM_DIGITS; i++ )
{
numbers[ i ] = 0;
}

if ( startValue < 0 )
{
startValue = 0;
}

for ( int i = NUM_DIGITS - 1; i >= 0 ; i-- )
{
numbers[ i ] = inputValue % 10;
inputValue /= 10;
}
}

// Preincrement Operator
void HugeInteger::eek:perator++( )
{
HugeInteger one( 1 );

cout << "*this: " << *this << endl;

*this = (*this).add( one );

cout << "*this: " << *this << endl;

cout << "test..." << endl;

return;
}

// Adds a HugeInteger + a HugeInteger
HugeInteger HugeInteger::add( HugeInteger operand2 )
{
HugeInteger newHugeInt( 0 );
int newElement = 0;
int carry = 0;

for ( int i = NUM_DIGITS - 1; i >= 0; i-- )
{
newElement = numbers[ i ] + operand2.getElementAt( i ) + carry;

// Once carry is used, reset to 0
carry = 0;

// Checks to see if newElement is greater than 10
if ( newElement >= 10 )
{
newElement = newElement - 10;
carry = 1;
}

// Sets new element into the HugeInteger
newHugeInt.setElementAt( i, newElement );

}


return newHugeInt;
}

// Sets the index value of the array to newElement value
void HugeInteger::setElementAt( const int index, const int newElement )
{
if ( ( index >= 0 ) && ( index < NUM_DIGITS ) )
{
numbers[ index ] = newElement;
}

return;
}

//--- Overloaded stream operators ---//

// Overloaded cout
ostream &operator<<( ostream &output, HugeInteger &hugeInt )
{
output << hugeInt.outputInteger();

return output;
}

// outputInteger() outputs the value of the string
string HugeInteger::eek:utputInteger()
{
string str1(" ");
bool displayAll = false;

for ( int i = 0; i < NUM_DIGITS; i++ )
{
// Don't display if numbers is 0
if ( ( numbers[ i ] == 0 ) && ( !displayAll ) )
{
}
else
{
displayAll = true;
char ch1[2];
ch1[0] = numbers[ i ] + '0';
ch1[1] = '\0';
string str2(ch1);
str1.append( str2 );
}
}


return str1;
}


****************************
TestHugeInteger.cpp // Driver
****************************

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

using std::cout;
using std::endl;

// Main Method
int main()
{

HugeInteger tempInt1(111);

cout << "tempInt1: " << tempInt1 << endl;

cout << "Line 91: Reached here..." << endl;

++tempInt1;

cout << "++tempInt1" << tempInt1 << " ) " << endl;

cout << "Line 96: Reached here..." << endl;

cout << "tempInt1: " << tempInt1 << endl;


// Indicates successful termination
return 0;
}
 
H

Huck Phin

Thank you for correcting me on the proper posting procedures. I should

have looked at this prior to posting. I have put in the necessary code

for one to compile and view the error that I am having. I have been
working on a different alternative, and that is to return a void value
from the function, and just change the value of the object from inside
of the function. The same problem occurs, which is weird. I have 3
files for my program. (1) HugeInteger.h for my header file, (2),
HugeInteger.cpp which includes my function definitions, and (3)
TestHugeInteger.cpp, which is my driver program. Thank you again for
your patience and time.

*******************
HugeInteger.h
*******************


#include <iostream>


using std::eek:stream;
using std::istream;


#include <string>


using std::string;


class HugeInteger {


//--- Overloaded stream operators ---//
friend ostream &operator<<( ostream &output, HugeInteger &hugeInt );

friend istream &operator>>( istream &input, HugeInteger &hugeInt );


public:
//--- Constructor Methods ---//
HugeInteger( int startValue );
HugeInteger( HugeInteger &hugeInt );


//--- Overloaded shortcut arithmetic operators ---//
void operator++(); // preincrement operator


//--- Transformer Methods ---//
HugeInteger add( HugeInteger operand2 );
void setElementAt( const int index, const int newElement );


//--- Accessor Methods ---//
string outputInteger();
int getElementAt( int index );


//--- Constant Declarations ---//
static const int NUM_DIGITS = 10;


private:
int numbers[ NUM_DIGITS ];



};


****************************
HugeInteger.cpp
****************************

#include <iostream>
#include "HugeInteger.h"
#include <string>


using std::cout;
using std::endl;


// Copy constructor
HugeInteger::HugeInteger( HugeInteger &otherHugeInt )
{
for ( int i = 0; i < NUM_DIGITS; i++ )
{
numbers[ i ] = otherHugeInt.getElementAt( i );
}



}


// Gets int element at specified index value
int HugeInteger::getElementAt( int index )
{
if ( ( index < 0 ) || ( index > NUM_DIGITS - 1 ) )
{
index = 0;
}

return numbers[ index ];



}


// Constructor method taking int value
HugeInteger::HugeInteger( int startValue )
{
int inputValue = startValue;

for ( int i = 0; i <= NUM_DIGITS; i++ )
{
numbers[ i ] = 0;
}


if ( startValue < 0 )
{
startValue = 0;
}


for ( int i = NUM_DIGITS - 1; i >= 0 ; i-- )
{
numbers[ i ] = inputValue % 10;
inputValue /= 10;
}



}


// Preincrement Operator
void HugeInteger::eek:perator++( )
{
HugeInteger one( 1 );

cout << "*this: " << *this << endl;


*this = (*this).add( one );


cout << "*this: " << *this << endl;


cout << "test..." << endl;


return;



}


// Adds a HugeInteger + a HugeInteger
HugeInteger HugeInteger::add( HugeInteger operand2 )
{
HugeInteger newHugeInt( 0 );
int newElement = 0;
int carry = 0;

for ( int i = NUM_DIGITS - 1; i >= 0; i-- )
{
newElement = numbers[ i ] + operand2.getElementAt( i ) + carry;


// Once carry is used, reset to 0
carry = 0;


// Checks to see if newElement is greater than 10
if ( newElement >= 10 )
{
newElement = newElement - 10;
carry = 1;
}


// Sets new element into the HugeInteger
newHugeInt.setElementAt( i, newElement );


}


return newHugeInt;



}


// Sets the index value of the array to newElement value
void HugeInteger::setElementAt( const int index, const int newElement )

{
if ( ( index >= 0 ) && ( index < NUM_DIGITS ) )
{
numbers[ index ] = newElement;
}

return;



}


//--- Overloaded stream operators ---//

// Overloaded cout
ostream &operator<<( ostream &output, HugeInteger &hugeInt )
{
output << hugeInt.outputInteger();


return output;



}


// outputInteger() outputs the value of the string
string HugeInteger::eek:utputInteger()
{
string str1(" ");
bool displayAll = false;

for ( int i = 0; i < NUM_DIGITS; i++ )
{
// Don't display if numbers is 0
if ( ( numbers[ i ] == 0 ) && ( !displayAll ) )
{
}
else
{
displayAll = true;
char ch1[2];
ch1[0] = numbers[ i ] + '0';
ch1[1] = '\0';
string str2(ch1);
str1.append( str2 );
}
}


return str1;



}


****************************
TestHugeInteger.cpp // Driver
****************************

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


using std::cout;
using std::endl;


// Main Method
int main()
{


HugeInteger tempInt1(111);


cout << "tempInt1: " << tempInt1 << endl;


cout << "Line 91: Reached here..." << endl;


++tempInt1;


cout << "++tempInt1" << tempInt1 << " ) " << endl;


cout << "Line 96: Reached here..." << endl;


cout << "tempInt1: " << tempInt1 << endl;


// Indicates successful termination
return 0;


}


// Had to repost due to forgetting the brace at the end.
 
H

Huck Phin

Oh my God. I found the error, and I am ashamed of it. The error is
right here.

for ( int i = 0; i <= NUM_DIGITS; i++ )
{
numbers[ i ] = 0;
}

It is an off by one error, which sent my pointer off the board when I
was running my for loop. I found the problem, and am going to bed,
because that one really took it out of me.

I have grown to hate the zero-indexing. I really do.

Just one of my little adventures, I guess.
~Huck Phin
 
M

mlimber

Huck said:
Oh my God. I found the error, and I am ashamed of it. The error is
right here.

for ( int i = 0; i <= NUM_DIGITS; i++ )
{
numbers[ i ] = 0;
}

It is an off by one error, which sent my pointer off the board when I
was running my for loop.

Precisely. Undefined behavior that resulted in a crash later.
I have grown to hate the zero-indexing. I really do.

It has its advantages, too.

Cheers! --M
 
B

BobR

Huck Phin wrote in message ...
Oh my God. I found the error, and I am ashamed of it. The error is
right here.

for ( int i = 0; i <= NUM_DIGITS; i++ ){
numbers[ i ] = 0;
}

It is an off by one error, which sent my pointer off the board when I
was running my for loop. I found the problem, and am going to bed,
because that one really took it out of me.

I have grown to hate the zero-indexing. I really do.

Memorize this line:

"The *first* thing is at *offset* zero.".
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,149
Latest member
Vinay Kumar Nevatia0
Top