0

注: 私はこれまでこの規模の問題を経験したことがなく、レイアウトの仕方がよくわかりません。間違ってレイアウトした場合は、どのようにレイアウトすればよいか説明してください。プログラムを手伝ってもらえない、または手伝ってくれない場合は、問題について教えていただければ幸いです。

オブジェクト指向プログラミングを実践するためにコードを書いていますが、今まで見たことのないエラーに遭遇しました (私はこれに数か月しかかからず、多くの時間を割くことができません)。義務教育に時間を浪費しているから学ぶ)。カーネル自体が (明らかに) 私のコードでこのエラーを生成しました。しかし、(デバッグ シンボルを使用して) gdb を実行しても、行番号はわかりませんでした。printf ステートメントを入れると、条件が満たされていない場合でも while ループをループしていることが明らかになりましたか? 条件が満たされていないにもかかわらず、ループし続けているように見えるので、これは奇妙に思えます。これが発生したときにエラーが発生する理由(私は思う)は、「スタック」クラスのどこかで、整数配列の負のサイズのメモリを再割り当てするためです-ただし、Stack::reloc に if ステートメントを追加して、負の配列サイズを再割り当てするのを防ぐと、エラーが発生します。見下ろすと、他のいくつかの情報が表示されます(gdbを引用):

プログラムがシグナル SIGABRT を受信し、中止されました。__kernel_vsyscall () の 0x0012d422

私は SIGABRT の wiki ページからあまり学ばなかったし、16 進数は私にとって何の意味もないと思います。これが私のコードで、2つのクラスとメインに分かれています:

ヘッダー:

#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

4 に答える 4

5

大きな問題が 1 つあります。realloc() 行は次のようになります。

stack = realloc(stack, (size+diff));
于 2011-08-21T11:33:30.680 に答える
1

標準ライブラリはすでにスタック実装を提供しているため、独自に実装している理由がわかりません。あなたの問題は、デストラクタ、コピー コンストラクタ、またはコピー代入演算子を提供していないことです。デストラクタが呼び出されると、ポインタは解放されますが、それが指しているオブジェクトは解放されません。これにより、メモリ リークが発生します。同様に、コピー コンストラクターまたは代入演算子が呼び出されると、ポインターが指すオブジェクトではなく、ポインターがコピーされます。デストラクタを適切に定義し、コピー関数を定義していない場合、オブジェクトが (不適切に) コピーされた場合、存在しないオブジェクトを削除する可能性があります。

もう 1 つの問題は、使用方法がrealloc間違っていることです。それは本当にあるべきです:

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

これは、割り当ての場所が変更された場合です。編集:別の回答からのコメントのおかげで、私が気付いたもう1つsizeof(int)のことは、サイズがバイト単位であると予想されるため、サイズに を掛ける必要があることです。

前述の問題は、プログラムが無限にループする理由ではありませんが、言及する価値はありました。本当の問題はループです。topループが 0 以下 (場合によっては 1 未満) で実行されることを期待しています。top0 はスタック内にそれ以上の要素がないことを示すため、実際には whileは0より大きいはずです。スタックが 0 未満のインデックスの要素にアクセスできるようにしているため、エラーが発生しています。とにかく、ループは一度しか条件を満たさないように見えるので、それらを削除できます。

于 2011-08-21T12:06:58.003 に答える
1

メモリの破損が原因で、プログラムが誤動作し、クラッシュしています。

あなたの場合、これはおそらく無効なポインターを介して書き込むことが原因です。ポインタを直接使用するコードの部分はStackクラスのみであるためStack、バグがあるか、誤って使用されるUniverse原因となるバグがある可能性があります。Stack

于 2011-08-21T11:35:16.963 に答える
0

プログラムのどこかで、無効なポインターを使用しようとしました。特に初心者にとっては、メモリの破損を見つけるのは困難です。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<T>またはのような標準ライブラリ コンテナを使用しますstd::vector<T>。必要になるまでポインタをいじらないでください。
  • mallocandを使用しないでください。必要に応じて andfreeを使用newdeleteてください。
  • 反復コードを減らすために、x、y、質量、速度などのデータをデータ構造に入れてみてください。
于 2011-08-21T12:17:19.627 に答える