C++ run time error with protected members
I am trying to do a homework assignment where we insert a string into a string at a specified point using a linked stack, hence the struct and typedef. Anyway, when I try to access stringLength in the StringModifier class inside the InsertAfter method, I get a run time error and I cannot figure out what the problem is. I should be able to access and modify the variable because it's protected and the derived class is inherited publicly.
struct StringRec
{
char theCh;
StringRec* nextCh;
};
typedef StringRec* StringPointer;
class String
{
public:
String();
~String();
void SetString();
void OutputString();
int GetLength() const;
protected:
StringPointer head;
int stringLength;
};
class StringModifier : public String
{
public:
StringModifier();
~StringModifier();
void InsertAfter( StringModifier& subString, int insertAt );
};
void StringModifier::InsertAfter( StringModifier& subString, int insertAt )
{
// RUN TIME ERROR HERE
stringLength += subString.strin开发者_如何学CgLength;
}
in MAIN
StringModifier test;
StringModifier test2;
cout << "First string" << endl;
test.SetString();
test.OutputString();
cout << endl << test.GetLength();
cout << endl << "Second string" << endl;
test2.SetString();
test2.OutputString();
cout << endl << test2.GetLength();
cout << endl << "Add Second to First" << endl;
test.InsertAfter( test2, 2 );
test.OutputString();
cout << endl << test.GetLength();
//String Class
String::String()
{
head = NULL;
stringLength = 0;
}
String::~String()
{
// Add this later
}
void String::SetString()
{
StringPointer p;
char tempCh;
int i = 0;
cout << "Enter a string: ";
cin.get( tempCh );
// Gets input and sets it to a stack
while( tempCh != '\n' )
{
i++;
p = new StringRec;
p->theCh = tempCh;
p->nextCh = head;
head = p;
cin.get( tempCh );
}
stringLength = i;
}
void String::OutputString()
{
int i = stringLength;
int chCounter;
StringPointer temp;
// Outputs the string bottom to top, instead of top to bottom so it makes sense when read
while( head != NULL && i > 0 )
{
temp = head;
chCounter = 0;
while( temp != NULL && chCounter < (i-1) )
{
temp = temp->nextCh;
chCounter++;
}
cout << temp->theCh;
i--;
}
}
int String::GetLength() const
{
return stringLength;
}
The StringModifier class has empty constructors and destructors.
Just a hint: Runtime errors in C++ are completely unrelated to public/protected/private access. The compiler, when compiling your code, has already checked that all the class member access rules are followed.
A runtime error means that you've got a bug in your program, most probably memory corruption of some kind.
Are you sure about run time error location? How did you checked that? I see one place which is very suspicious:
while( temp != NULL && chCounter < (i-1) )
{
temp = temp->nextCh;
chCounter++;
}
cout << temp->theCh; // temp can be NULL here?
Either temp != NULL is always true in loop header or in some cases you do have NULL pointer dereference which is itself a run time error.
You can try running your program under Valgrind (free) or Purify (probably not free) to detect memory errors as early as possible. The error message should also be much more clear.
Also, just run the program under a debugger, and when it crashes, check its state. Is it what you expect?
Are you sure your runtime error actually happens in the InsertAfter function? It looks to me like when you modify the stringLength you should get an access violation in OutputString because you haven't actually added the characters yet. Adding the (temp != NULL) clause to your while loop almost avoids this - but look at what happens if you actually leave the loop because of temp becoming NULL...
Responding to your comments: I'm afraid I'm still a bit skeptical about where this runtime error is happening! If the code really is as given in the question, and assuming you've not got a messed-up build, having an AV or something in InsertAfter would be nigh-on impossible (OK, that's a dangerous thing to say in C++, but hey - you're just changing the value of a member of an object that is allocated on the stack). Note that you can't tell that the error is occurring in the InsertAfter method just because it goes away if you don't call it - indeed the bug in OutputString is only exposed by the call to InsertAfter, so it should disappear if the InsertAfter call is removed. To check, either use a debugger, or add some logging to InsertAfter, both before and after the suspect statement.
Thanks for everyone's help. It turns out I was adding things to the list wrong to begin with. Instead of making it a stack I made it a Queue and all is working great! I took advice you guys gave and looked elsewhere for the problem. Thank You!
void String::SetString()
{
StringPointer p, last;
char tempCh;
last = head;
int i = 0;
cout << "Enter a string: ";
cin.get( tempCh );
while( tempCh != '\n' )
{
i++;
if( i == 1 )
{
p = new StringRec;
p->theCh = tempCh;
head = p;
last = p;
}
else
{
p = new StringRec;
p->theCh = tempCh;
p->nextCh = last;
last->nextCh = p;
last = p;
}
cin.get( tempCh );
}
last->nextCh = NULL;
stringLength = i;
}
精彩评论