ошибка памяти (нарушение доступа) по параметрам метода - PullRequest
0 голосов
/ 02 февраля 2012

У меня странная проблема. Я пытаюсь написать простую игру на C ++, но у меня не получилось с объектами и типами данных. Там есть код:

// C++
// Statki

#include <stdio.h>
#include <time.h>
#include <map>
#include <vector>
#include <string>
#include <list>

#define D true

using namespace std;

void _(char* message){printf("%s\n",message);};

struct relpoint { int x,y; };
struct point { int x,y; };
struct size { int w,h; };

map<const char*, vector<relpoint> > shipshape;
list<char*> shipTypes = {"XS", "S", "M", "L", "XL"};

string alpha="ABCDEFGHIJKLMNOPRSTUVWXYZ";

enum fieldtype { UNKNOWN=-1,EMPTY=0,SHIP=1,HIT=2,MISS=3,};

enum rotation { EAST=0, SOUTH=1, WEST=2, NORTH=3 };

class Ship
{
    char* type;

};

class Sea
{
    public:
    void init(size mapsize) { init( mapsize, EMPTY ); };
    void init(size mapsize, fieldtype fill)
    {
        if(D)printf("Generating sea\n");
        vector<fieldtype> v;

        seamap.reserve(mapsize.h);
        v.reserve(mapsize.w);

        for (int y=0; y<mapsize.h; y++)
        {
            v.clear();
            for(int x=0; x<mapsize.w; x++)
            {
                v.push_back(fill);
            }
            seamap.push_back(v);
        }

        view();
    };

    bool place_ship(Ship ship);

    void view()
    {
        for( vector< vector<fieldtype> >::const_iterator yy = seamap.begin(); yy != seamap.end(); ++yy )
        {
            for( vector<fieldtype>::const_iterator xx = (*yy).begin(); xx != (*yy).end(); ++xx )
            {
                if(D)printf("%d ", *xx);
            }
            if(D)printf("\n");
        }
    };

    private:
    vector< vector<fieldtype> > seamap;
};

class Game
{
    public:

    void initmap(size mapsize)
    {
        if(D) printf("\nInit %d×%d map\n", mapsize.w, mapsize.h);

        (*enemymap).init(mapsize, UNKNOWN);
        //(*selfmap).init(mapsize);
    };

    bool placeship(string type, point position, rotation rotate);
    fieldtype shoot(point target);
    void viewmap(){(*selfmap).view();};

    bool eog();

    Sea * enemymap;
    Sea * selfmap;
};

class Bot
{
    public:

    void init(size mapsize)
    {
        if(D)_("Init Bot");
    }

    private:

    Game * g;
};

class Player
{

    public:
    Player() { if(D){_("Player fake init");} };

    void init(size mapsize)
    {
        (*g).initmap(mapsize);
    };

    void viewmap(){(*g).viewmap();};

    private:
    Game * g;

};

class Router
{

    public:

    void startgame();
    void welcomescreen()
    {
        printf("\n\n\n\t\t\tShips minigame\n\t\t\t\tby Kris\n\n");

        mainmenu();
    };
    void mainmenu()
    {
        printf("Menu (type letter):\n\tN: New game\n\tS: Settings\n\tQ: Quit game\n\n > ");

        char opt;
        opt = toupper(getchar());

        size ms;

        switch(opt)
        {
            case 'N':
                ms = getmapsize();
                (*P1).init(ms);
                (*P2).init(ms);
            break;

            case 'S':

            break;

            case 'Q':

            break;

            default:
                printf("Invalid option %c", opt);
                mainmenu();
        }
    };

    private:
    Player * P1;
    Bot    * P2;

    size getmapsize()
    {
        size ms;
        printf("\nSet map size (X Y)\n > ");
        scanf("%d %d", &ms.w, &ms.h);
        return ms;
    };
};

int main () {

    vector<relpoint> shp;
    shp.reserve(5);
    list<char*>::const_iterator tp = shipTypes.begin();
    shp.push_back({0,0});
    shipshape[*(tp++)] = shp;
    shp.push_back({1,0});
    shipshape[*(tp++)] = shp;
    shp.push_back({2,0});
    shipshape[*(tp++)] = shp;
    shp.push_back({3,0});
    shipshape[*(tp++)] = shp;
    shp.push_back({2,1});
    shipshape[*tp] = shp;

    Router R;
    R.welcomescreen();

    printf("\n\n");
    return 0;
}

Может быть скомпилировано, но после строки Инициализация 5 × 5 map Программа останавливается с Naruszenie ochrony pamięci ( Нарушение доступа к памяти на польском). Кажется, проблема возникает в обеих Sea::init() функциях.

Я собираю его с помощью g++ -std=c++0x -Wno-write-strings ships2.cpp (для предотвращения предупреждений) в Ubuntu.

Есть идеи, что с ним не так?

Ответы [ 3 ]

2 голосов
/ 02 февраля 2012

Все классы содержат указатели, но вы никогда не инициализируете указатели или не выделяете место для объектов, на которые они должны указывать.

Делаете это

 (*enemymap).init(mapsize, UNKNOWN);

, когда enemymap не делаетНе указывайте нигде, это почти верный способ получить нарушение доступа.

0 голосов
/ 02 февраля 2012

+ 1 для Бо.Но ради себя:

скомпилируйте с -g, а затем

gdb ./mygame.bin
type 'run'

after setting the map size 5 5 :

Program received signal SIGSEGV, Segmentation fault.
mainmenu (this=<optimized out>) at memacvio.cpp:158
158                 (*P1).init(ms);

Это должно сказать вам, что P1, вероятно, не является действительным указателем.

0 голосов
/ 02 февраля 2012

Вы используете неинициализированный указатель. Вы можете исправить это, создав экземпляр объекта здесь или в конструкторе где-то еще.

Вот пример создания экземпляра в вызове initmap.

void initmap(size mapsize)
{
    // Initialize the pointer by instantiating a class
    enemymap = new Sea;
    if(D) printf("\nInit %d×%d map\n", mapsize.w, mapsize.h);

    (*enemymap).init(mapsize, UNKNOWN);
    //(*selfmap).init(mapsize);
};
...