简体   繁体   English

受保护成员的C ++运行时错误

[英]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. 我正在尝试做一个作业分配,其中我们使用链接堆栈在指定点将字符串插入字符串,因此使用struct和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. 无论如何,当我尝试在InsertAfter方法内的StringModifier类中访问stringLength时,出现运行时错误,并且我无法弄清楚问题出在哪里。 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.stringLength;
}

in MAIN 在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. StringModifier类具有空的构造函数和析构函数。

Just a hint: Runtime errors in C++ are completely unrelated to public/protected/private access. 只是一个提示:C ++中的运行时错误与公共/受保护/私有访问完全无关。 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 your runtime error actually happens in the InsertAfter function? 您确定您的运行时错误实际上发生在InsertAfter函数中吗? 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. 在我看来,当您修改stringLength时,您应该在OutputString中遇到访问冲突,因为您实际上尚未添加字符。 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... 在您的while循环中添加(temp!= NULL)子句几乎可以避免这种情况-但请查看如果由于temp变为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). 如果代码确实是问题中给出的,并且假设您没有搞砸的构建,那么在InsertAfter中拥有AV或其他内容几乎是不可能的(好吧,这在C ++中是很危险的事情,但是嘿-您只是在更改在堆栈上分配的对象的成员的值)。 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. 请注意,您不能仅仅因为不调用而导致错误消失,就无法判断出InsertAfter方法中发生了错误-实际上,OutputString中的错误仅通过对InsertAfter的调用而暴露,因此,如果InsertAfter方法出现,则该错误消失通话被删除。 To check, either use a debugger, or add some logging to InsertAfter, both before and after the suspect statement. 要进行检查,请在可疑语句之前和之后使用调试器,或在InsertAfter中添加一些日志记录。

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. temp!= NULL在循环标头中始终为true,或者在某些情况下确实存在NULL指针取消引用,这本身就是运行时错误。

You can try running your program under Valgrind (free) or Purify (probably not free) to detect memory errors as early as possible. 您可以尝试在Valgrind(免费)或Purify(可能不是免费)下运行程序,以尽早发现内存错误。 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? 是您所期望的吗?

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM