指针给出seg错误

Pointers give seg fault

本文关键字:错误 seg 指针      更新时间:2023-10-16

这是程序

    #include <iostream>
    #include <time.h>
    #include <conio.h>
    #include <cstdlib>
    #include <windows.h>
    using namespace std;
    const int widht = 117,height = 26;
    class Paddle
    {
    private:
        int y;
        int originalY;
    public:
        Paddle()
        {        
            y=height/2-2;
            originalY=y;
        }
        inline int getY()
        {
            return y;
        }
        inline void moveUp()
        {
            y--;
        }
        inline void moveDown()
        {
            y++;
        }
        void checkWall()
        {
            if (y<0)
            {
                while (y<0)
                {
                y++;
                }
            }
            else if (y>height)
            {
                while (y>height)
                {
                y--;
                }
            }
        }
        void Reset()
        {
        y=originalY;
        }
    };
    class Ball
    {
    private:
        int x,y;
        int originalX,originalY;
    public:
        Ball()
        {
            x=widht/2;
            y=height/2;
            originalX=x;
            originalY=y;
        }
        inline int getX()
        {
            return x;
        }
        inline int getY()
        {
            return y;
        }
        inline void moveRight()
       {
            x++;
       }
        inline void moveUpRight()
        {
            x++;
            y--;
        }
        inline void moveDownRight()
        {
            x++;
            y++;
        }
        inline void moveLeft()
        {
            x--;
        }
        inline void moveUpLeft()
        {
            y--;
            x--;
        }
        inline void moveDownLeft()
        {
            y++;
            x--;
        }
        inline void Reset()
        {
            x=originalX;
            y=originalY;
       }
    };
    class Manager
    {
    private:
        int score1,score2;
        int columns, rows;
    public:
        int p1y;
        int p2y;
        int ballX,ballY;
        bool gameOver;
        Manager()
        {
            gameOver = false;
        }
        void Draw(Paddle *p1,Paddle *p2,Ball *b)
        {  
            system("cls");
            p1y=p1->getY();
            p2y=p1->getY();
            ballX=b->getX();
            ballY=b->getY();
            for (int i=0;i<height;i++)
            {
                for (int j=0;j<widht;j++)
                {
                    if (i==p1y && j==2)
                    {
                        cout << "xDB";
                    }
                    else if (i==p1y+1 && j==2)
                    {
                        cout << "xDB";
                    }
                    else if (i==p1y+2 && j==2)
                    {
                        cout << "xDB";
                    }
                    else if (i==p1y+3 && j==2)
                    {
                        cout << "xDB";
                    }
                    else if (i==p1y+4 && j==2)
                    {
                        cout << "xDB";
                    }
                    else if (i==p2y && j==widht-1)
                    {
                        cout << "xDB";
                    }
                    else if (i==p2y+1 && j==widht-1)
                    {
                        cout << "xDB";
                    }
                    else if (i==p2y+2 && j==widht-1)
                    {
                        cout << "xDB";
                    }
                    else if (i==p2y+3 && j==widht-1)
                    {
                        cout << "xDB";
                    }
                    else if (i==p2y+4 && j==widht-1)
                    {
                        cout << "xDB";
                    }
                    else if (i==ballX && j==ballY)
                    {
                        cout << "O";
                    }
                    cout << " ";
                }
                cout << endl;
            }
            cout << p1 -> getY();
        }
        void Input(Paddle *p1,Paddle *p2)
        {
            if (_kbhit())
            {
                switch(_getch())
                {
                    case 'w':
                        p1->moveUp();
                        break;
                    case 's':
                        p1->moveDown();
                        break;
                    case 'i':
                        p2->moveUp();
                        break;
                    case 'k':
                        p2->moveDown();
                        break;
                }
            }
        }
        void Run(Paddle *p1,Paddle *p2, Ball *b)
        {
            while(!gameOver)
            {
                Draw(p1,p2,b);
                Input(p1,p2);
                Sleep(10);
            }
        }
    };
    int main()
    {
        Paddle *p1;
        Paddle *p2;
        Ball *b;
        Manager *m;
        m->Run(p1,p2,b);
        return 0;
    }

我不明白为什么当我启动程序时(使用调试器)会出现分段错误。我认为原因是指针,因为在它完美工作之前(但没有修改值);有什么建议吗?

您从未为分配任何内存,也从未初始化

Paddle *p1;
Paddle *p2;
Ball *b;
Manager *m;

使用这些指针是未定义的行为。

您不应该使用指针,而应该将所有对象更改为常规的自动对象,如

Paddle p1;
Paddle p2;
Ball b;
Manager m;

然后在函数中通过引用而不是通过指针传递它们。

您没有向主方法中指向PaddleBallManager变量的指针分配任何内容。

默认情况下,不会初始化,而是指向内存中的某个位置,您的应用程序可能无法访问该位置。当您访问它们并且内存不可访问时,就会出现您所观察到的访问冲突或segfault。

你可以采取两种方法。如果您更改主菜单如下:

int main()
{
    Paddle p1;
    Paddle p2;
    Ball b;
    Manager m;
    m.Run(&p1,&p2,&b);
    return 0;
}

然后,每个类的一个实例将存在于堆栈上。由于应用程序在m.Run返回后退出,因此使用这种方法是安全的,因为对象的生存期比Run调用的代码长。

或者,您可以在堆上分配它们。在这种情况下,您可以使用:

int main()
{
    std::unique_ptr<Paddle>( new Paddle );
    std::unique_ptr<Paddle>( new Paddle );
    std::unique_ptr<Ball>( new Ball );
    std::unique_ptr<Manager>( new Manager );
    m->Run(p1.get(),p2.get(),b.get());
    return 0;
}

unique_ptr将保存一个指向堆上分配的Paddle等的指针,并在main方法返回后自动为您清理。

    Manager *m;
    m->Run(p1,p2,b);

在为变量赋值之前,不能使用变量的值。你没有给m赋值,但你立即使用它。这不可能正确。

代码Manager *m;只是声明了一个名为m的类型为pointer to Manager的变量。但它还没有指向任何东西。

代码m->Run(p1,p2,b);调用m所指向的Manager上的Run方法。如果m没有指向类Manager的实例,那么这样做毫无意义。