Поврежденный двойной связанный список: 0x0804d0c0 (C++)?

ПРИМЕЧАНИЕ: у меня никогда не было проблем такого масштаба, и я не знаю, как их выложить, если я выложил их неправильно, объясните, пожалуйста, как мне их выложить. Если вы не можете или не будете помогать с программой, я рад просто узнать о проблеме.

Я писал фрагмент кода, чтобы попрактиковаться в объектно-ориентированном программировании, но я столкнулся с ошибкой, которую я никогда раньше не видел (я занимался этим всего несколько месяцев и не уделял много времени учиться, потому что мое время тратится на обязательное образование). Само ядро ​​(видимо) выдало эту ошибку с моим кодом. Но запуск gdb (с символами отладки) не дал мне представления о номере строки. Вставка оператора printf показала, что он зацикливается на цикле while, даже если условие больше не выполняется? Это кажется мне странным, потому что кажется, что условие не выполнено, но оно продолжает работать. Причина, по которой он исправляет ошибку (я думаю), когда это происходит, заключается в том, что где-то в классе "Stack" он перераспределяет память отрицательного размера для целочисленного массива - хотя, когда я добавил оператор if в Stack::reloc, чтобы предотвратите переопределение отрицательных размеров массива, это все еще исправляет ошибку. Посмотрев вниз, вы увидите несколько других фрагментов информации (цитируя gdb):

Программа получила сигнал SIGABRT, Прервано. 0x0012d422 в __kernel_vsyscall ()

Я не многому научился на вики-странице для SIGABRT, и я не думаю, что шестнадцатеричное число что-то значит для меня. Вот мой код, разделенный на два класса и основной:

заголовки:

#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 ()

4 ответа

Одна большая проблема, строка realloc() должна быть:

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

Стандартная библиотека уже обеспечивает реализацию стека, поэтому я не понимаю, почему вы реализуете свою собственную. Проблема с вашим заключается в том, что вы не предоставили деструктор, конструктор копирования или оператор присваивания копии. Когда вызывается деструктор, он освобождает указатель, но не объект, на который он указывает. Это приведет к утечке памяти. Аналогично, когда вызывается конструктор копирования или оператор присваивания, он будет копировать указатель, а не объект, на который он указывает. Если вы правильно определили деструктор, но не функции копирования, вы можете удалить несуществующие объекты, если объект был скопирован (неправильно).

Другая проблема заключается в том, что вы используете realloc неправильно. Это действительно должно быть:

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

Это в случае, если место размещения меняется. Изменить: Еще одна вещь, которую я заметил, благодаря комментарию из другого ответа, что вы должны умножить размер на sizeof(int), поскольку он ожидает размер в байтах.

Вышеупомянутые проблемы не являются причиной того, что ваша программа работает бесконечно, но это стоило упомянуть. Настоящая проблема - это петли. Вы ожидаете, что циклы будут выполняться top меньше или равно 0 (или меньше 1 в одном случае). Действительно, это должно быть top больше 0, так как 0 указывает, что в стеке больше нет элементов. Так как вы разрешаете стеку обращаться к элементам с индексами меньше 0, вы получаете ошибку. Похоже, что петли могут соответствовать их состоянию только один раз, так что вы можете удалить их.

Ваша программа плохо себя ведет и падает из-за повреждения памяти.

В вашем случае это, вероятно, вызвано записью через неверный указатель. Поскольку единственная часть вашего кода, которая напрямую использует указатели, это ваша Stack класс, вероятно, что либо Stack есть ошибка, или Universe есть ошибка, которая вызывает Stack быть использован неправильно.

Где-то в вашей программе вы пытались использовать недопустимый указатель. Повреждение памяти трудно найти, особенно для начинающих. Цитируя Брайана Кернигана: "Когда вы изо всех сил будете писать свой код, как вы будете его отлаживать?" GDB может помочь вам в сложных программах, но в этом случае я бы пошел в другом направлении.

к счастью Stack кажется, единственное место в вашей программе, имеющее дело с памятью. Я бы посоветовал добавить некоторые утверждения в его методы:

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

Это поможет вам найти ошибки в других частях вашего кода, которые неправильно используют ваш класс Stack:

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

Это вызовет переполнение стека, даже если Stack было бы правильно. Как указали другие ответы, realloc не установил указатель.

Есть и другие моменты, я бы возразил против вашего кода:

  • Используйте стандартные библиотечные контейнеры, такие как std::stack<T> или же std::vector<T>, Не возиться с указателями, пока не придется.
  • Не использовать malloc а также freeиспользовать new а также delete если вам нужно.
  • Попытайтесь поместить данные как x, y, масса, скорость в структуру данных, чтобы уменьшить количество повторяющегося кода.
Другие вопросы по тегам