分段故障删除节点

segmentation fault deleting nodes

本文关键字:节点 删除 故障 分段      更新时间:2023-10-16

当我编译这个代码时,我得到了一个分段错误,我相信这是由这个块引起的。

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

我发现指针是非常混乱的,有一个指针不是指向内存中的有效对象,但我不确定如何解释它。我明白,我需要重新分配"下一个"(或"链接"我如何在我的代码中命名)指针的对象被删除之前,到下一个指针,对象被删除后。我试图用代码做到这一点,但我仍然得到segfault。有人能解释给我是怎么回事,并帮助我了解如何解决这个问题吗?

        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 << "tttt-Salary in the range of ($45,000 - $60,000)-n" << "Printed in format: First Name, Last Name, Salary, Bonus, Deduction, Net Salary.nn";
    //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;
    }

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

当到达列表末尾时,必须跳出外层循环。

我看到了两个类似的问题。

一个是iter = iter->link两次。Once在for循环中,Once在while循环中。你可能只需要一个控制回路。

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

那么想象一下下面的数据集:15000,16000

for循环指向15000节点。现在它进入while循环。由于15000超出了范围,它执行iter = iter->link,并且iter现在指向16000节点。然后删除15000节点。while循环再次运行,看到16000超出了范围。它执行iter = iter->link,现在iter指向null。删除16000节点。while循环再次运行,但现在传递给它null!

我将把它更改为使用while循环或for循环,并且只有一个地方检查null并移动到下一个节点。

在你的while循环iter可以指向列表的结束,然后在netSalary(iter)你传递空指针(如果我假设你的列表是由空指针结束)。你的函数可以吗?或者你可以输入return iter->salary;

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

我不知道你是否修复了它,但是我看到当你销毁一个节点时,你不会删除到被删除项目的前一个链接。我试过了,希望能有所帮助

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