【问题标题】:Why does this code cause the program to crash?为什么这段代码会导致程序崩溃?
【发布时间】:2014-10-05 09:59:59
【问题描述】:
void gameListType::sortAscending() {

    nodeType<gameType> *current;
    nodeType<gameType> *next;
    nodeType<gameType> *prev;
    nodeType<gameType> *temp;

    temp = first;
    prev = first;
    current = first;
    next = current->link;

    while ( current->link !=NULL){
        if (current ==first){
             if (current->info.getPrice() > next->info.getPrice()){
            temp->info = current -> info;
            temp->link = next ->link;
            next -> link = temp;
            current = temp;
            delete temp;
            }
        }
        else if (current !=first ){
            if (current->info.getPrice() > next->info.getPrice()){
                temp->info = current->info;
                temp-> link = next ->link;
                next->link = temp;
                prev->link = next;
                current = temp;
                delete temp;
            }
        }
        if(current == first){
            prev = first;
        }
        else{
            prev = prev->link;
        }
        current = current ->link;
        next = next->link;
    }
}

运行此代码会导致我的程序崩溃,有什么想法吗?这基本上是对 CUSTOM 链表中的项目进行排序。它显然只在循环完成一次后崩溃,所以第二个循环是为什么它崩溃的问题。

【问题讨论】:

  • 我注意到next-&gt;link 上没有有效性检查。你可能会在那里得到一个空指针。
  • 当您设置current = temp;,然后设置delete temp;,那么current 将指向一个不再存在的对象。稍后您访问current-&gt;link 等,这肯定是导致崩溃的可能原因之一。
  • 首先找出程序崩溃的确切行。
  • 你删除了临时文件。只是评论它。有效吗?
  • 改用std::sort有什么问题?

标签: c++ crash iterator


【解决方案1】:

您的代码崩溃是因为您将 temp 变量视为指向一个临时对象,但它实际上指向您正在排序的列表中的一个对象。

走这条简单的路:

temp = first;
prev = first;
current = first; // temp == first and current == first, so temp == current
next = current->link;

while ( current->link !=NULL){          // true
    if (current ==first){               // true
        if (current->info.getValue() > next->info.getValue()){ // true
            temp->info = current->info; // temp == current, so nothing changes
            temp->link = next->link;    // temp == current, so current->link = next->link
            next -> link = temp;        // temp == current, so next->link = current
            current = temp;             // temp == current, so nothing changes
            delete temp;                // temp == current, so delete both temp and current
        }
    }
// ...
    current = current ->link;         // but we deleted current! segfault

else if 块中存在完全相同的问题(您的示例中有一些代码重复)。通过为temp 变量创建一个新的临时对象来消除该问题。请注意,单独为info 提供一个临时地址就足够了:

if (current->info.getValue() > next->info.getValue()){
    // No need to mess with pointers here, current and next are advanced later
    // Bonus points for using a swap function instead
    InfoClass temp = current->info;
    current->info = next->info;
    next->info = temp;
}

这种方法不会修改nextcurrent 指针,从而解决了函数中的另一个问题(即next-&gt;link 指向current 而不是current-&gt;link 指向next)。


我想在此说明另一点,即即使已修复,您的函数实际上也不会执行排序;它只执行bubble sort 的单次传递,它将列表中的最大值“推”到正确的位置(即:列表的末尾)。即使正确实施,冒泡排序也是一种效率低下的算法,在平均情况下具有二次复杂度。

Merge sort 是用于对列表进行排序的常用算法。或者,根据您要排序的内容,简单地将数据复制到向量中,使用std::sort 对其进行排序并从排序后的数据中重建列表可能会有所帮助(这种方法实现起来最简单,但最不容易出错合并排序总是写起来很有趣)。

【讨论】:

    猜你喜欢
    • 2018-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 2019-09-08
    相关资源
    最近更新 更多