【问题标题】:linked list segmentation fault fixed with cerr用 cerr 修复的链表分段错误
【发布时间】:2013-12-26 11:09:58
【问题描述】:

我有以下代码。这段代码的作用是合并两个已排序的链表,然后删除两个链表并返回一个新列表:

#include <iostream>

using namespace std;

class node {
    public:
        node(int, node*);
        node* get_next() const;
        void set_next(node*);
        int get_item() const;
        void set_item(int);
    private:
        int item;
        node* next;
};

node* clone_and_destroy(node* a)
{
    node* new_list;
    node* prev;
    node* ret_val;
    while ( a )
    {
        new_list = new node(a->get_item(),NULL);
        if ( prev ){
            prev->set_next(new_list);
            prev = prev->get_next();
        }
        else{
        prev = new_list;
        ret_val = prev;
        }
        node* temp = a;
        a = a->get_next();
        delete temp;
    }
    return ret_val;
}

node* merge(node*& a, node*& b){
    if ( !a ){// cerr<<"\r";
        return clone_and_destroy(b);}
    if ( !b )
        return clone_and_destroy(a);

    node* smaller_node, *bigger_node;
    if ( a->get_item() < b->get_item() ){
        smaller_node = a;
        bigger_node = b;
    }
    else {
        smaller_node = b;
        bigger_node = a;
    }
    node* next_node = smaller_node->get_next(); 
    node* merged_list = new node(smaller_node->get_item(),smaller_node->get_next());
    delete smaller_node;
    merged_list->set_next(merge(next_node,bigger_node));
    a = NULL ;
    b = NULL ;
    return merged_list;
}

/*node* merge(node*& a, node*& b){
    if ( !a )
        return b;
    if ( !b )
        return a;
    if ( a->get_item() < b->get_item() ){
        node* a_next = a->get_next();
        node* merged_list = a;
        merged_list->set_next(merge(a_next,b));
        delete a;
        return merged_list;
    }
    else {
        node* b_next = b->get_next();
        node* merged_list = b;
        merged_list->set_next(merge(a,b_next));
        delete b;
        return merged_list;
    }
}*/     

void print(node* a)
{   
    while ( a )
    {
        cout << a->get_item() << " ";
        a = a->get_next();
    }
    cout << endl;
}

node::node(int _item, node* _next)
{
    item = _item;
    next = _next;
}
node* node::get_next() const
{
    return next;
}
void node::set_next(node* new_next)
{
    next = new_next;
}
int node::get_item() const { return item; }
void node::set_item(int _item)
{ 
    item = _item;
}

int main() {
    node* l1 = NULL, *l2 = NULL;
    cout << "Before Merging: " << endl;
    for (int i = 5; i > 0; i--) {
        l1 = new node(i, l1);
        l2 = new node(2*i-3, l2);
    }
    cout << "List 1 is: \t\t";
    print(l1);
    cout << endl;
    cout << "List 2 is: \t\t";
    print(l2);
    cout << endl << "After Merging:" << endl;
    node* m = merge(l1, l2);
    cout << "List 1 is: \t\t";
    print(l1);
    cout << "Should be: \t\t[ ]" << endl;
    cout << endl;
    cout << "List 2 is: \t\t";
    print(l2);
    cout << "Should be: \t\t[ ]" << endl;
    cout << endl;
    cout << "Merged List is: \t";
    print(m);
    cout << "Should be: \t\t[ -1 1 1 2 3 3 4 5 5 7 ]" << endl;


    for (node* h = m; h != NULL; h = m) {
        m = m->get_next();
        delete h;
    }
    return 0;
}

代码的重要部分是合并功能,其余的只是实现此功能的工具。现在发生了一件有趣的事情!这段代码在我运行时出现分段错误,但是当我尝试调试我的代码时,我在合并函数的第一行使用了 cerr(它已被注释),突然它工作正常了!!!有人可以向我解释一下吗!这个cerr在做什么?!以及如何在没有此 cerr 且对代码进行最少更改的情况下修复我的代码!?现在我知道 cerr 会阻止 couts 缓冲,但我认为这里不是这种情况!

【问题讨论】:

  • 未定义的行为很奇怪。使用调试器。
  • 我已经花了足够的时间了!即使使用了调试器,我也需要别人的意见

标签: c++ linked-list segmentation-fault


【解决方案1】:

*prev 没有用任何东西初始化,您正在尝试访问它。因此段。故障。

node* clone_and_destroy(node* a) { .. ..

     if ( prev ){

编辑:初始化它将修复 seg 错误。但你检查它背后的逻辑。

node* prev = NULL;

Edit2:为什么 cerr 修复分段错误

Code crashes unless I put a printf statement in it

从中抽象“问题问“为什么 printf() 语句'修复'事情”。答案是因为它解决了问题。你有一个 Heisenbug,因为分配的内存被滥用,并且printf() 的存在设法稍微改变了代码的行为。”

【讨论】:

  • 只是要写,但是 if(prev) 不是访问 - 指针可能是内存中任何地方的随机指针
  • 即使是这样,为什么cerr会修复它?!??谢谢,这实际上修复了我的错误
  • @Ashkan if(prev) 仅检查指针是否为空,它可能在内存中的任何位置都无效(访问指向无效内存的非空指针是段错误)
  • @AshkanKzme 是的,没有访问它。但是您可以在访问它之后看到行。问题是检查失败,因为 prev 可能有垃圾值。
  • 好的,所以如果你编辑你的答案并添加这部分也会有帮助
猜你喜欢
  • 2019-06-20
  • 1970-01-01
  • 2020-12-07
  • 1970-01-01
  • 2018-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多