与圆形链表崩溃

时间:2016-12-07 23:19:43

标签: c++

我正在尝试实现一个链表(我相信这是一个循环链表),但在使用它时,它最终会崩溃。我认为这是因为我使用的遍历指针未正确设置为0,并最终解除引用并显示未定义的行为。

感谢您的帮助。

这是我正在使用的功能:

struct records t_head = 0;

struct records* find_id(Rect a)
{

    struct records* tmp;
    struct records* prev;

    // Add first node
    if (t_head == NULL) {
        tmp = new records;
        tmp->b = a;
        tmp->id = trecord_count + 1;
        tmp->tally.resize(labelsInfo.size());
        tmp->frames = 0;
        t_head = tmp;
        t_head->next = NULL;
        trecord_count++;
    }

    else {
        // Check if there is any node that has delete_flag set first
        tmp = t_head;
        while (tmp) {

            if (delete_flag) {

                // Delete here
                if (tmp == t_head) {
                    t_head = tmp->next;
                    delete (tmp);
                    trecord_count--;
                }
                else {
                    prev->next = tmp->next;
                    delete (tmp);
                    trecord_count--;
                }
            }

            prev = tmp;
            tmp = tmp->next;
        }

        tmp = new records;
        tmp->b = a;
        tmp->id = trecord_count + 1;
        tmp->tally.resize(labelsInfo.size());
        tmp->frames = 0;
        tmp->next = t_head;
        t_head = tmp;
        trecord_count++;
    }

    return tmp;
}

结构定义是:

struct records {
int id;
Rect b;
vector<int> tally= {};
int frames=0;
int delete_flag=0;
struct records *next;
};

1 个答案:

答案 0 :(得分:0)

以下代码会运行,但它也会显示评论中已提及的缺陷。

  1. 在您的版本中,您可以访问刚刚在循环中删除的tmp中的指针,以便使用集delete_flag搜索记录。这在以下版本中已得到纠正。所需的修改标有//< Tobias。请注意,在linux下使用valgrind可以轻松找到此类错误。 Andon M. Coleman也提到了in his comment
  2. 在您的find_id版本中,实际上没有搜索a已实施。我在我的版本中实现了这样的搜索。
  3. 如果删除列表中间的某些记录,则结束记录会保留其ID,但您会减少trecord_count并再次分配相同的ID。因此,您最终会得到具有相同ID的多个记录。
  4. 编辑:我在程序中添加了一些日志记录。也许,这可以帮助您了解发生了什么。此外,我滥用frames作为真实id。即,没有两个记录具有相同的frames - 值。记录在括号中,完整列表在方括号中。并且您没有循环列表。也许,您会得到错误的印象,因为您在前面添加了新记录,因此,您需要使用t_head的旧值作为新创建记录的next指针的值。 / p>

    该计划的输出是:

    g++ -std=c++11 -g -O0 ./test.cc -o a.exe && ./a.exe
    Returning { frames=1 id=1 b=1 }
    Full content:
    [ { frames=1 id=1 b=1 } ]
    
    Adding { frames=2 id=2 b=2 }
    Returning { frames=2 id=2 b=2 }
    Full content:
    [ { frames=2 id=2 b=2 }, { frames=1 id=1 b=1 } ]
    
    Adding { frames=3 id=3 b=3 }
    Returning { frames=3 id=3 b=3 }
    Full content:
    [ { frames=3 id=3 b=3 }, { frames=2 id=2 b=2 }, { frames=1 id=1 b=1 } ]
    
    Deleting head { frames=3 id=3 b=3 }
    Adding { frames=4 id=3 b=4 }
    Returning { frames=4 id=3 b=4 }
    Full content:
    [ { frames=4 id=3 b=4 }, { frames=2 id=2 b=2 }, { frames=1 id=1 b=1 } ]
    
    Returning { frames=2 id=2 b=2 }
    Full content:
    [ { frames=4 id=3 b=4 }, { frames=2 id=2 b=2 }, { frames=1 id=1 b=1 } ]
    
    Deleting { frames=2 id=2 b=2 }
    Adding { frames=5 id=3 b=5 }
    Returning { frames=5 id=3 b=5 }
    Full content:
    [ { frames=5 id=3 b=5 }, { frames=4 id=3 b=4 }, { frames=1 id=1 b=1 } ]
    
    
    At exit: [ { frames=5 id=3 b=5 }, { frames=4 id=3 b=4 }, { frames=1 id=1 b=1 } ]
    

    以下是名为test.cc的程序:

    #include <vector>
    #include <iostream>
    #include <cstdlib>
    
    typedef int Rect;
    
    struct records {
        int id;
        Rect b;
        std::vector<int> tally= {};
        int frames=0;
        int delete_flag=0;
        struct records *next;
    };
    
    struct records *t_head = 0;
    int trecord_count = 0;
    int trecord_frames = 0;
    
    std::ostream& operator << (std::ostream& os, const records& r) {
        os << "{ frames=" << r.frames << " id=" << r.id << " b=" << r.b << " }";
        return os;
    }
    
    std::ostream& operator << (std::ostream& os, const records* r) {
        os << "[ ";
        if(r)
            os << *r;
        for(r=r->next; r; r=r->next)
            std::cout << ", " << *r;
        std::cout << " ]\n";
    }
    
    struct records* find_id(Rect a)
    {
    
        struct records* tmp;
        struct records* prev;
    
        // Add first node
        if (t_head == NULL) {
            tmp = new records;
            tmp->b = a;
            tmp->id = trecord_count + 1;
            tmp->tally.resize(0);
            tmp->frames = ++trecord_frames;
            t_head = tmp;
            t_head->next = NULL;
            trecord_count++;
        }
    
        else {
            // Check if there is any node that has delete_flag set first
            tmp = t_head;
            while (tmp) {
    
                if (tmp->delete_flag) {
    
                    // Delete here
                    if (tmp == t_head) {
                        std::cout << "Deleting head " << *tmp << std::endl;
                        t_head = tmp->next;
                        delete (tmp);
                        trecord_count--;
                        tmp = t_head; //< Tobias
                    }
                    else {
                        std::cout << "Deleting " << *tmp << std::endl;
                        prev->next = tmp->next;
                        delete (tmp);
                        trecord_count--;
                        tmp = prev->next; //< Tobias
                    }
                } else {
                    prev = tmp;
                    tmp = tmp->next;
                }
            }
    
            // Search for the id
            tmp = t_head;
            while(tmp && (tmp->b != a))
                tmp = tmp->next;
    
            if(!tmp) {
                tmp = new records;
                tmp->b = a;
                tmp->id = trecord_count + 1;
                tmp->tally.resize(0);
                tmp->frames = ++trecord_frames;
                tmp->next = t_head;
                t_head = tmp;
                std::cout << "Adding " << *tmp << std::endl;
                trecord_count++;
            }
        }
    
        std::cout << "Returning " << *tmp << std::endl;
        std::cout << "Full content:\n" << t_head << std::endl;
    
        return tmp;
    }
    
    int main() {
        find_id(1);
        find_id(2);
        find_id(3);
    
        t_head->delete_flag=1;
        find_id(4);
    
        records* r = find_id(2);
        r->delete_flag = 1;
        find_id(5);
    
        std::cout << "\nAt exit: " << t_head;
    
        return 0;
    }
    
    /*
        Local Variables:
        compile-command: "g++ -std=c++11 -g -O0 ./test.cc -o a.exe && ./a.exe"
        End:
    */
    
相关问题