如何在访问指针的值时保护应用程序免受读取访问冲突?

时间:2019-03-19 21:00:31

标签: c++

我创建了一些类似链的结构,其中一个对象具有指向链的下一个和上一个对象的指针。下面的代码遍历整个链,查找在参数中指定的值,并删除匹配的元素(如果存在)。

void List::removeElementByValue(int value)
{
    ListMember* nextElem = this->firstValue;
    while (nextElem) {
        if (nextElem == NULL || nextElem == nullptr) {
            break;
        }

        if (nextElem->value == value) {
            if (nextElem->prevValue)
                (nextElem->prevValue)->nextValue = nextElem->nextValue;
            if (nextElem->nextValue)
                (nextElem->nextValue)->prevValue = nextElem->prevValue;
            delete nextElem;
            this->count--;
            return;
        }
        nextElem = nextElem->prevValue;
    }
}

问题是:当我试图从链中删除不存在的值时出现此错误。

  

抛出异常:读取访问冲突。 nextElem是0xCDCDCDCD。

在这种情况下,函数应该什么也不做。它发生在这一行:

 if (nextElem->value == value) {

如您所见,我已经使用多种方法来检查nextElem是否正确,但是仍然出现此错误。有什么方法可以防止这种情况发生?

1 个答案:

答案 0 :(得分:1)

  

if (nextElem == NULL || nextElem == nullptr)

while (nextElem)为true时,它将始终为false。

  

nextElem = nextElem->prevValue;

这需要使用nextValue而不是prevValue

但是,最重要的是,如果在列表的第一个元素中找到了this->firstValue,则不会更新value,因此最终您将删除firstValue并使其指向无效的内存。

尝试以下方法:

void List::removeElementByValue(int value)
{
    ListMember* elem = this->firstValue;
    while (elem) {
        if (elem->value == value) {
            if (elem->prevValue)
                elem->prevValue->nextValue = elem->nextValue;
            if (elem->nextValue)
                elem->nextValue->prevValue = elem->prevValue;

            // ADD THIS!!!
            if (elem == this->firstValue)
                this->firstValue = elem->nextValue;

            delete elem;
            this->count--;
            return;
        }

        elem = elem->nextValue;  // NOT prevValue!
    }
}

更好的解决方案是首先不要手动实现链接列表。请改用标准std::list容器,让它为您完成所有艰苦的工作。

#include <list>

class List
{
private:
    std::list<int> values;
    ...
};

...

#include <algorithm>

void List::removeElementByValue(int value)
{
    auto iter = std::find(values.begin(), values.end(), value);
    if (iter != values.end())
        values.erase(iter);
}