【问题标题】:corrupted double-linked list: 0x0804d0c0 (C++)?损坏的双链表:0x0804d0c0 (C++)?
【发布时间】:2011-08-21 11:19:37
【问题描述】:

注意:我以前从未遇到过这种规模的问题,也不知道如何布置,如果我布置错了,请解释我应该如何布置。如果您不能或不愿为该计划提供帮助,我很高兴了解这个问题。

我一直在编写一段代码来练习面向对象编程,但是我遇到了一个我以前从未见过的错误(我只做了几个月并且没有得到很多学习的时间,因为我的时间浪费在义务教育上)。内核本身(显然)用我的代码产生了这个错误。但是运行 gdb(带有调试符号)并没有让我知道行号。放入 printf 语句表明即使不再满足条件,它也在循环 while 循环?这对我来说似乎很奇怪,因为它似乎没有满足条件,但它一直在循环。发生这种情况时它通过错误(我认为)的原因是因为在“Stack”类中的某个地方它为整数数组重新分配了负大小的内存 - 但是,当我向 Stack::reloc 添加一个 if 语句以防止它重新分配负数组大小,它仍然会通过错误。向下看会显示其他几条信息,(引用 gdb):

程序收到信号 SIGABRT,已中止。 __kernel_vsyscall()中的0x0012d422

我并没有真正从 SIGABRT 的 wiki 页面中学到很多东西,而且我认为十六进制数字对我没有任何意义。这是我的代码,分为两个类和main:

标题:

#include <cstdio>
#include <cstdlib>

类堆栈:

class Stack {
private:
    int *stack;
    int size;
    void init(int *top) {
        *top = 0;
    }

    void push2(int *s,int* top, int element) {
        s[(*top)++] = element;
    }

    int pop2(int *s,int *top) {
        return s[--(*top)];
    }
    void reloc(int diff) {
        if ((top+diff)>1) {
            realloc(stack, (size+diff));
            size = size+diff;
        }
    }

public:
    int top;
    Stack() {
        init(&top);
        size = 100;
        stack = (int *)malloc(100 * sizeof(int));
    }
    void push(int element) {
        if (top>=(size-1)) reloc(100);
        push2(stack, &top, element);
    }
    int pop() {
        if ((top<(size-120)) && (top>100)) reloc(-100);
        return (pop2(stack, &top));
    }
    int sth() {
        return size;
    }

};

类宇宙:

/*Universe is the casual layout for the universe*/
class Universe {
    private:
        int y_cog; //y axis center of gravity
        int x_cog; //x axis "
        int force; //weight of universe
        int fps; //frames per second
        int g; //acceleration under gravity
        int G; //gravitational constant

        //NB: velocity in d/s
        //all stacks defined
        Stack y_pos; //y axis position
        Stack x_pos; //x axis "
        Stack mass; //mass of object
        Stack y_vel; //velocity on y axis
        Stack x_vel; //velocity on x axis
        Stack y_pos2; //stacks for repeating
        Stack x_pos2;
        Stack mass2;
        Stack y_vel2;
        Stack x_vel2;

        //function 'increments' the center of gravity
        void cog(int y, int x, int m) {
            //ratio is offset of universe cog
            //where 100 is exectly half way
            int ratio = ((m*100)/(force))/2;
            //set the center of gravity the ratio beween the objects
            y_cog = y_cog-(((y_cog-y)/100)*ratio);
            x_cog = x_cog-(((x_cog-x)/100)*ratio);
            force = m+force;
        }

        /*moves the object at the top of the stack and alters velocity
        according to previouse velocity and force towards the universe
        center of gravity*/
        void move() {
            int yp, xp, m, yv, xv, vi, yvi, xvi, rm;
            yp = y_pos2.pop();
            xp = x_pos2.pop();
            m = mass2.pop();
            yv = y_vel2.pop();
            xv = x_vel2.pop();
            //important part
            //set the position according to velocity and frame rate
            yp = yp+(yv/fps);
            xp = xp+(xv/fps);
            //find the ratio share of velocity
            vi = ((g*100)/fps); //velocity increase
            rm = ((y_cog-yp)+(x_cog-xp)); //ratio maximum
            if (rm==0) rm = 1;
            yvi = ((vi/rm)*(y_cog-yp))/100;
            xvi = ((vi/rm)*(x_cog-xp))/100;
            yv = yvi;
            xv = xvi;
            //push everything back
            y_pos.push(yp);
            x_pos.push(xp);
            mass.push(m);
            y_vel.push(yv);
            x_vel.push(xv);
        }

    public:
        Universe() {
            y_cog = 0;
            x_cog = 0;
            force = 0;
            fps = 10;
            g = 10;
            //all stacks initialised
            y_pos = Stack();
            x_pos = Stack();
            mass = Stack();
            y_vel = Stack();
            x_vel = Stack();
        }

        void add(int yp, int xp, int m, int yv, int xv) { //adds object to stack
            y_pos.push(yp);
            x_pos.push(xp);
            mass.push(m);
            y_vel.push(yv);
            x_vel.push(xv);
        }

        void run() {
            int yp, xp, m, yv, xv;
            while (y_pos.top<=0) { //reposition center of gravity
                //mainly pushing things around
                yp = y_pos.pop();
                xp = x_pos.pop();
                m = mass.pop();
                yv = y_vel.pop();
                xv = x_vel.pop();
                cog(yp, xp, m); //the important part
                y_pos2.push(yp);
                x_pos2.push(xp);
                mass2.push(m);
                y_vel2.push(yv);
                x_vel2.push(xv);
            }
            while (y_pos2.top<1) {
                move();
            }
        }

        void outh() { //human output
            int yp, xp, m, yv, xv;
            while (y_pos.top<=0) {
                yp = y_pos.pop();
                xp = x_pos.pop();
                m = mass.pop();
                yv = y_vel.pop();
                xv = x_vel.pop();
                y_pos2.push(yp);
                x_pos2.push(xp);
                mass2.push(m);
                y_vel2.push(yv);
                x_vel2.push(xv);
                printf("%d, %d\t%d\t%d\n", yp, xp, m, yv+xv);
            }
            while (y_pos2.top<=0) {
                y_pos.push(y_pos2.pop());
                x_pos.push(x_pos2.pop());
                mass.push(mass.pop());
                y_vel.push(y_vel.pop());
                x_vel.push(x_vel.pop());
            }
        }       
};

主函数:

int main() {
    Universe main = Universe();
    main.add(10, 10, 10, 0, 0);
    main.add(5, 5, 5, 0, 0);
    int i;
    for (i = 1; i<100; i++) {
        main.run();
        main.outh();
        printf("\n");
    }
    return 0;
}

GDB 运行结果(带调试符号):

Starting program: /home/james/Desktop/coding/Universe/debug 
*** glibc detected *** /home/james/Desktop/coding/Universe/debug: corrupted double-linked list: 0x0804d0c0 ***
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6(+0x6b591)[0x2d4591]
/lib/tls/i686/cmov/libc.so.6(+0x70ce3)[0x2d9ce3]
/lib/tls/i686/cmov/libc.so.6(realloc+0xdd)[0x2d9f9d]
/home/james/Desktop/coding/Universe/debug[0x80486b2]
/home/james/Desktop/coding/Universe/debug[0x804872c]
/home/james/Desktop/coding/Universe/debug[0x80489b0]
/home/james/Desktop/coding/Universe/debug[0x8048cec]
/home/james/Desktop/coding/Universe/debug[0x80485fd]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0x27fbd6]
/home/james/Desktop/coding/Universe/debug[0x80484d1]
======= Memory map: ========
00110000-0012b000 r-xp 00000000 08:01 393241     /lib/ld-2.11.1.so
0012b000-0012c000 r--p 0001a000 08:01 393241     /lib/ld-2.11.1.so
0012c000-0012d000 rw-p 0001b000 08:01 393241     /lib/ld-2.11.1.so
0012d000-0012e000 r-xp 00000000 00:00 0          [vdso]
0012e000-00217000 r-xp 00000000 08:01 2625203    /usr/lib/libstdc++.so.6.0.13
00217000-00218000 ---p 000e9000 08:01 2625203    /usr/lib/libstdc++.so.6.0.13
00218000-0021c000 r--p 000e9000 08:01 2625203    /usr/lib/libstdc++.so.6.0.13
0021c000-0021d000 rw-p 000ed000 08:01 2625203    /usr/lib/libstdc++.so.6.0.13
0021d000-00224000 rw-p 00000000 00:00 0 
00224000-00248000 r-xp 00000000 08:01 525255     /lib/tls/i686/cmov/libm-2.11.1.so
00248000-00249000 r--p 00023000 08:01 525255     /lib/tls/i686/cmov/libm-2.11.1.so
00249000-0024a000 rw-p 00024000 08:01 525255     /lib/tls/i686/cmov/libm-2.11.1.so
0024a000-00267000 r-xp 00000000 08:01 393299     /lib/libgcc_s.so.1
00267000-00268000 r--p 0001c000 08:01 393299     /lib/libgcc_s.so.1
00268000-00269000 rw-p 0001d000 08:01 393299     /lib/libgcc_s.so.1
00269000-003bc000 r-xp 00000000 08:01 525247     /lib/tls/i686/cmov/libc-2.11.1.so
003bc000-003bd000 ---p 00153000 08:01 525247     /lib/tls/i686/cmov/libc-2.11.1.so
003bd000-003bf000 r--p 00153000 08:01 525247     /lib/tls/i686/cmov/libc-2.11.1.so
003bf000-003c0000 rw-p 00155000 08:01 525247     /lib/tls/i686/cmov/libc-2.11.1.so
003c0000-003c3000 rw-p 00000000 00:00 0 
08048000-0804a000 r-xp 00000000 08:01 132105     /home/james/Desktop/coding/Universe/debug
0804a000-0804b000 r--p 00001000 08:01 132105     /home/james/Desktop/coding/Universe/debug
0804b000-0804c000 rw-p 00002000 08:01 132105     /home/james/Desktop/coding/Universe/debug
0804c000-0806d000 rw-p 00000000 00:00 0          [heap]
b7e00000-b7e21000 rw-p 00000000 00:00 0 
b7e21000-b7f00000 ---p 00000000 00:00 0 
b7fed000-b7fef000 rw-p 00000000 00:00 0 
b7ffe000-b8000000 rw-p 00000000 00:00 0 
bffeb000-c0000000 rw-p 00000000 00:00 0          [stack]

Program received signal SIGABRT, Aborted.
0x0012d422 in __kernel_vsyscall ()

【问题讨论】:

  • 在这么多代码中很难发现错误。为了您自己和我们的利益,您应该尝试在不删除错误的情况下删除尽可能多的代码。例如,Universe::move() 中的计算可能与错误无关。尝试取出可能不相关的代码,编译、运行并重复,只要您仍然可以看到错误。最后剩下的应该揭示原因:)
  • 问题标题似乎具有误导性。我在您的代码中没有看到双链表。
  • @Rene 它来自 GDB 的错误可能是内存错误。用户也可以使用调试符号进行编译吗?看起来你不是那么 gdb 只是给出地址而不是符号名称
  • 我承认编写自己的 Stack 作为编程练习,但我想问一下 - 你是否也知道 std::stackstd::vectorstd::list
  • 我同意耶稣拉莫斯的观点。您似乎没有使用调试符号编译程序。将 -g 添加到编译器命令行。同样在运行您的应用程序之前,在控制台中执行“ulimit -c unlimited”,以便应用程序在崩溃时生成核心转储。然后你可以在 gdb 中打开它,看看出了什么问题。

标签: c++ arrays oop loops sigabrt


【解决方案1】:

一个大问题,realloc() 行应该是:

stack = realloc(stack, (size+diff));

【讨论】:

  • stack = realloc(stack, (size+diff) * sizeof(int));
  • 谢谢,我应该猜到了(看看我是如何在 Stack::Stack 中使用 malloc 的)我还需要指定它需要和整数数组:stack = (int *)realloc(stack, (大小+差异) * sizeof(int));
【解决方案2】:

由于内存损坏,您的程序运行不正常并崩溃。

在您的情况下,这可能是由于写入无效指针造成的。由于您的代码中唯一直接使用指针的部分是您的Stack 类,因此Stack 可能存在错误,或者Universe 存在导致Stack 使用不正确的错误。

【讨论】:

    【解决方案3】:

    标准库已经提供了堆栈实现,所以我不明白您为什么要实现自己的。您的问题是您没有提供析构函数、复制构造函数或复制赋值运算符。当析构函数被调用时,它会释放指针,但不会释放它指向的对象。这将导致内存泄漏。同样,当调用复制构造函数或赋值运算符时,它会复制指针,而不是它指向的对象。如果您正确定义了析构函数,但未正确定义复制函数,则如果对象已被复制(不正确),您可能会删除不存在的对象。

    另一个问题是您错误地使用了realloc。确实应该是:

    stack = realloc(stack, (size + diff) * sizeof(int));
    

    这是在分配位置发生变化的情况下。编辑:由于另一个答案的评论,我注意到的另一件事是,您必须将大小乘以 sizeof(int),因为它需要以字节为单位的大小。

    上述问题并不是程序无限循环的原因,但值得一提。真正的问题是循环。您期望循环在 top 小于或等于 0(或在一种情况下小于 1)时执行。实际上,应该是当top 超过 0,因为 0 表示堆栈中没有更多元素。由于您允许堆栈访问索引小于 0 的元素,因此您会收到错误消息。看起来循环只能满足一次条件,所以你可以删除它们。

    【讨论】:

      【解决方案4】:

      您在程序的某个地方尝试使用无效指针。内存损坏很难找到,尤其是对于初学者。引用 Brian Kernighan 的话:“当您尽最大努力编写代码时,您将如何调试它?” GDB 可以帮助你处理复杂的程序,但在这种情况下,我会转向另一个方向。

      幸运的是,Stack 似乎是您的程序中唯一处理内存的地方。 我的建议是在它的方法中加入一些断言,如下所示:

      // at the beginning of pop():
        assert(top > 1);
      

      这将帮助您发现代码的其他部分中滥用您的 Stack 类的错误:

      while (y_pos.top<=0) {
        yp = y_pos.pop();
      

      即使Stack 是正确的,这也会导致堆栈下溢。正如其他答案指出的那样,realloc 没有设置指针。

      还有其他几点,我反对你的代码:

      • 使用标准库容器,如std::stack&lt;T&gt;std::vector&lt;T&gt;。除非必要,否则不要乱用指针。
      • 不要使用mallocfree,如果必须使用newdelete
      • 尝试将 x、y、质量、速度等数据放入数据结构中,以减少重复代码。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-01-01
        • 1970-01-01
        • 2015-09-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多