分段故障删除节点

时间:2014-07-03 20:18:42

标签: c++ pointers segmentation-fault

编译此代码时出现分段错误,我相信这是由此块引起的。

EmployPtr iter;    
//Deletes nodes outside of range.
while(netSalary(iter)<45000 || netSalary(iter)>60000)
{
    EmployPtr nodeToDelete = iter;
    iter = iter->link;
    delete nodeToDelete;
}

我发现指针非常混乱,并且有一个指针没有指向内存中的有效对象,但我不确定如何解释它。我知道我需要重新分配&#34; next&#34; (或者&#39;链接&#39;我如何在我的代码中命名)在被删除对象之前的对象指针,在删除对象之后的下一个指针。我尝试用代码做到这一点,但我仍然遇到了seg错误。任何人都可以向我解释发生了什么,并帮助我了解如何解决这个问题?

        EmployPtr nodeToDelete = iter->link;
        iter->link = nodeToDelete->link;
        delete nodeToDelete;

[包含其余代码,以防需要引用。]

#include <fstream>
#include <iostream>
using namespace std;

struct Employee
{
    string firstN;
    string lastN;
    float salary;
    float bonus;
    float deduction;

    Employee *link;
};

typedef Employee* EmployPtr;
void insertAtHead( EmployPtr&, string, string, float, float,float );
void insert( EmployPtr&, string, string, float, float,float );
float netSalary( EmployPtr& );

int main()
{
    //Open file
    fstream in( "payroll.txt", ios::in );

    //Read lines
    string first, last;
    float salary, bonus, deduction;
    EmployPtr head = new Employee;

    //Inserts all the data into a new node in the linked list, creating a new node each time the loop executes.
    while( in >> first >> last >> salary >> bonus >> deduction)
        insert (head, first, last, salary, bonus, deduction);

    //Close file
    in.close();

    cout << "\t\t\t\t-Salary in the range of ($45,000 - $60,000)-\n" << "Printed in format: First Name, Last Name, Salary, Bonus, Deduction, Net Salary.\n\n";

    //Deletes all nodes in the list that are not between 45,000 and 65,000. It then prints the newly modified list.
    EmployPtr iter;
    for(iter = head; iter!= NULL; iter = iter->link)
    {
        //Deletes nodes outside of range.
        while(netSalary(iter)<45000 || netSalary(iter)>60000)
        {
            EmployPtr nodeToDelete = iter;
            iter = iter->link;
            delete nodeToDelete;
        }

        //Prints list.
        cout << iter->firstN << ", " << iter->lastN << ", " << iter->salary << ", " << iter->bonus << ", " << iter->deduction << ", " << netSalary(iter) <<endl;
    }
        return 0;
}

void insertAtHead(EmployPtr& head, string firstValue, string lastValue,
            float salaryValue, float bonusValue,float deductionValue)
{
    //method definition
}

void insert(EmployPtr& afterNode, string firstValue, string lastValue,
        float salaryValue, float bonusValue,float deductionValue)
{
    //method definition
}

float netSalary(EmployPtr& node)
{
   //method definition
}

[更新代码]

    //Deletes nodes outside of range.
    while((netSalary(head)<45000 || netSalary(head)>60000) && head!=NULL)
    {
        EmployPtr nodeToDelete = head;
        head = head->link;
        delete nodeToDelete;
        nodeToDelete->link = head;
    }

        //Prints List
    EmployPtr iter;
    for(iter = head; iter!= NULL; iter = iter->link)
    {
        cout << iter->firstN << ", " << iter->lastN << ", " << iter->salary << ", " << iter->bonus << ", " << iter->deduction << ", " << netSalary(iter) <<endl;
    }

4 个答案:

答案 0 :(得分:0)

在你的while循环中,iter可以指向列表的末尾,然后在netSalary(iter)中传递空指针(如果我假设你的列表以空指针结束)。你的功能还可以吗?或者你只需​​要返回iter-&gt; salary;

编辑: 这只是一个猜测,因为你没有提供你的方法的实现。

答案 1 :(得分:0)

考虑当列表的最后一个元素的净工资低于45000或高于60000时会发生什么。最后一个元素的'link'指针(可能)是NULL,但你的内部循环不会检查它,所以删除该元素后,它会将NULL指针传递给netSalary函数。

当你到达列表的末尾时,你必须完全跳出外部循环。

答案 2 :(得分:0)

我看到两个类似的问题。

一个是你有iter = iter-&gt;链接两次。一旦进入for循环,一次进入while循环。你可能只需要一个控制循环。

另一个是while()循环从不检查iter是否为null。

想象一下以下数据集:15000,16000

for循环指向15000节点。现在它命中了while循环。由于15000超出范围,因此iter = iter-&gt; link并且iter现在指向16000节点。然后它删除15000节点。 while循环再次运行,并看到16000超出范围。它确实是iter = iter-&gt;链接,现在iter指向null。它删除16000节点。 while循环再次运行,但现在你将它传递为null!

我会将其更改为使用while循环或for循环,并且只有一个位置检查null并继续移动到下一个节点。

答案 3 :(得分:0)

我不知道你是否修复它,但我看到你在销毁一个节点时没有删除之前删除项目的链接。我尝试了一些东西,希望能有所帮助

EmployPtr iter = head;
EmployPtr prevIt = NULL; // pointer to previous node
while( iter )
{
    if(netSalary(head)<45000 || netSalary(head)>60000)
    {
        EmployPtr nodeToDelete = iter;
        iter = iter->link;
        delete nodeToDelete;

        if( prevIt )
            prevIt->link = iter;
        else
            head = iter; // this happens when the head needs to be deleted, so head must point to nex
    }
    else
    {
        prevIt = iter;
        iter = iter->link;
    }
}