поврежденный двойной связанный список: 0x0804d0c0 (C ++)? - PullRequest
0 голосов
/ 21 августа 2011

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

Я писал фрагмент кода, чтобы попрактиковаться в объектно-ориентированном программировании, но я столкнулся с ошибкой, которую я никогда раньше не видел (я занимался этим всего несколько месяцев и не получал много времени, чтобы учиться, потому что мое время тратится на обязательное образование). Само ядро ​​(видимо) выдало эту ошибку с моим кодом. Но запуск 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 ]

5 голосов
/ 21 августа 2011

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

stack = realloc(stack, (size+diff));
1 голос
/ 21 августа 2011

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

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

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

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

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

1 голос
/ 21 августа 2011

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

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

0 голосов
/ 21 августа 2011

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

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

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

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

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

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

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

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